Fixture 218

cpp lambdas and callables

C++ · 6 functions · 4 lanes · 22 of 24 function-lanes behave identically

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

Lambdas and the closure objects they compile to — the most common C++ abstraction in modern code, and one this corpus does not cover at all.

WHAT A LAMBDA ACTUALLY IS. An unnamed struct holding the captures, plus an operator(). Three capture modes produce three different objects:

* capture-by-value -> the captured object is COPIED into the closure, so the closure's field is a distinct storage location from the variable it came from; * capture-by-reference -> the field is a POINTER to the enclosing frame, so reads through it must be modelled as memory, not as a copy; * no capture -> an empty object with a static-like call operator, which every compiler inlines away entirely at -O2.

A decompiler that folds the by-value copy into a direct read of the original variable produces C that is right until the original is mutated after capture — which is exactly what capture_then_mutate does. That is a silent, plausible wrong answer, and it is the reason this fixture exists.

At -O0 each closure is a real stack object with a real operator() call; at -O2 most collapse to inline arithmetic. Both are worth covering: the -O0 lane tests object recovery and the -O2 lane tests that the collapse is followed.

10_cpp_runtime_shapes covers vtables, ctors/dtors and RAII; 137_cpp_templates covers monomorphization; 138_cpp_operators covers operator overloading on a named class. None of them constructs a closure, and none exercises a capture list. std::function is deliberately NOT used here: it would pull in libstdc++ type-erasure and heap allocation, which the corpus's no-libc, no-allocation rule excludes. The hand-written callable_ref below is the same indirection with none of the runtime.

tests/decompiler_fixtures/src/218_cpp_lambdas_and_callables.cpp source
#include <stdint.h>

/* Lambdas and the closure objects they compile to — the most common C++
 * abstraction in modern code, and one this corpus does not cover at all.
 *
 * WHAT A LAMBDA ACTUALLY IS. An unnamed struct holding the captures, plus an
 * `operator()`. Three capture modes produce three different objects:
 *
 *   * capture-by-value   -> the captured object is COPIED into the closure, so
 *                           the closure's field is a distinct storage location
 *                           from the variable it came from;
 *   * capture-by-reference -> the field is a POINTER to the enclosing frame, so
 *                           reads through it must be modelled as memory, not as
 *                           a copy;
 *   * no capture         -> an empty object with a static-like call operator,
 *                           which every compiler inlines away entirely at -O2.
 *
 * A decompiler that folds the by-value copy into a direct read of the original
 * variable produces C that is right until the original is mutated after
 * capture — which is exactly what `capture_then_mutate` does. That is a
 * silent, plausible wrong answer, and it is the reason this fixture exists.
 *
 * At -O0 each closure is a real stack object with a real `operator()` call; at
 * -O2 most collapse to inline arithmetic. Both are worth covering: the -O0 lane
 * tests object recovery and the -O2 lane tests that the collapse is followed.
 *
 * `10_cpp_runtime_shapes` covers vtables, ctors/dtors and RAII;
 * `137_cpp_templates` covers monomorphization; `138_cpp_operators` covers
 * operator overloading on a named class. None of them constructs a closure, and
 * none exercises a capture list. `std::function` is deliberately NOT used here:
 * it would pull in libstdc++ type-erasure and heap allocation, which the
 * corpus's no-libc, no-allocation rule excludes. The hand-written
 * `callable_ref` below is the same indirection with none of the runtime.
 */

/* Capture by value: `base` is copied into the closure. */
extern "C" __attribute__((noinline)) int32_t capture_by_value(int32_t base,
                                                   int32_t count) {
    if (count < 0 || count > 32) {
        return -1;
    }
    auto add_base = [base](int32_t v) { return v + base; };
    int32_t total = 0;
    for (int32_t i = 0; i < count; i++) {
        total += add_base(i);
    }
    return total;
}

/* Capture by reference: the closure holds a pointer into this frame, and the
 * accumulator is mutated through it. */
extern "C" __attribute__((noinline)) int32_t capture_by_reference(int32_t count) {
    if (count < 0 || count > 32) {
        return -1;
    }
    int32_t total = 0;
    auto accumulate = [&total](int32_t v) { total += v * 2; };
    for (int32_t i = 0; i < count; i++) {
        accumulate(i);
    }
    return total;
}

/* THE DISCRIMINATOR. `base` is captured by value and then mutated. A recovery
 * that reads the original variable instead of the closure's copy returns a
 * different number. */
extern "C" __attribute__((noinline)) int32_t capture_then_mutate(int32_t base) {
    auto snapshot = [base](int32_t v) { return v + base; };
    base += 1000;                    /* must NOT affect the closure */
    return snapshot(1) + base;
}

/* Mixed capture: one by value, one by reference, in one closure object. */
extern "C" __attribute__((noinline)) int32_t mixed_capture(int32_t scale, int32_t count) {
    if (count < 0 || count > 32) {
        return -1;
    }
    int32_t total = 0;
    auto step = [scale, &total](int32_t v) { total += v * scale; };
    for (int32_t i = 0; i < count; i++) {
        step(i);
    }
    return total;
}

/* Hand-written type erasure: a function pointer plus an environment pointer,
 * which is what `std::function` is underneath and what a captureless lambda
 * decays to. This is an INDIRECT CALL through a recovered object field. */
struct callable_ref {
    int32_t (*fn)(const void *env, int32_t value);
    const void *env;
};

struct scale_env {
    int32_t factor;
};

static int32_t scale_apply(const void *env, int32_t value) {
    return value * static_cast<const scale_env *>(env)->factor;
}

extern "C" __attribute__((noinline)) int32_t erased_callable(int32_t factor,
                                                  int32_t count) {
    if (count < 0 || count > 32) {
        return -1;
    }
    scale_env env{factor & 7};
    callable_ref call{&scale_apply, &env};
    int32_t total = 0;
    for (int32_t i = 0; i < count; i++) {
        total += call.fn(call.env, i);
    }
    return total;
}

/* CONTROL: the same arithmetic as an ordinary function call, no closure. */
static int32_t add_base_plain(int32_t v, int32_t base) { return v + base; }

extern "C" __attribute__((noinline)) int32_t plain_call_control(int32_t base,
                                                     int32_t count) {
    if (count < 0 || count > 32) {
        return -1;
    }
    int32_t total = 0;
    for (int32_t i = 0; i < count; i++) {
        total += add_base_plain(i, base);
    }
    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

5/6
capture_by_reference pass 26 lines
// glaurung: capture_by_reference @ 0x11a0
__attribute__((no_stack_protector)) int32_t capture_by_reference(int32_t arg0) {
    extern void _ZZ20capture_by_referenceENK3__1clEi(char *, int);
    unsigned char total[12];
    int i;
    unsigned char local_18[8];
    // x86-64 prologue: save rbp, frame 32 bytes
    if (((long)(arg0) < 0)) {
        *(int *)((&total[0] + 8)) = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(*(int *)((&total[0] + 8)));
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 32) | ((long)(arg0) < 32)) == 0)) {
        *(int *)((&total[0] + 8)) = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(*(int *)((&total[0] + 8)));
    }
    *(int *)(&total[0]) = 0;
    *(long *)(&local_18[0]) = (long)((long)(&total[0]));
    for (i = 0; (i < arg0); i++) {
        _ZZ20capture_by_referenceENK3__1clEi((char *)(&local_18[0]), (unsigned long)((unsigned int)(i)));
    }
    *(int *)((&total[0] + 8)) = *(int *)(&total[0]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(*(int *)((&total[0] + 8)));
}
capture_by_value pass 29 lines
// glaurung: capture_by_value @ 0x1100
__attribute__((no_stack_protector)) int32_t capture_by_value(int32_t arg0, int32_t arg1) {
    extern int _ZZ16capture_by_valueENK3__0clEi(char *, int);
    int total;
    int i;
    unsigned char local_10[4];
    int local_4;
    int var2;
    // x86-64 prologue: save rbp, frame 32 bytes
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    *(int *)(&local_10[0]) = arg0;
    total = 0;
    for (i = 0; (i < arg1); i++) {
        var2 = _ZZ16capture_by_valueENK3__0clEi((char *)(&local_10[0]), (unsigned long)((unsigned int)(i)));
        total = (var2 + total);
    }
    local_4 = total;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
capture_then_mutate pass 12 lines
// glaurung: capture_then_mutate @ 0x1240
__attribute__((no_stack_protector)) int32_t capture_then_mutate(int32_t arg0) {
    extern int _ZZ19capture_then_mutateENK3__2clEi(char *, int);
    unsigned char local_8[4];
    int var4;
    // x86-64 prologue: save rbp, frame 16 bytes
    *(int *)(&local_8[0]) = arg0;
    arg0 = ((unsigned int)(arg0) + 1000);
    var4 = _ZZ19capture_then_mutateENK3__2clEi((char *)(&local_8[0]), 1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((var4 + arg0));
}
erased_callable fail 31 lines
// glaurung: erased_callable @ 0x1340
__attribute__((no_stack_protector)) int32_t erased_callable(int32_t arg0, int32_t arg1) {
    int total;
    int i;
    unsigned char local_10[4];
    unsigned char local_20[16];
    int local_4;
    long var7;
    // x86-64 prologue: save rbp, frame 48 bytes
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    *(int *)(&local_10[0]) = ((unsigned long)((unsigned int)(arg0)) & 7);
    *(long *)(&local_20[0]) = (long)((long)(0x13e0));
    *(long *)((&local_20[0] + 8)) = (long)((long)(&local_10[0]));
    total = 0;
    for (i = 0; (i < arg1); i++) {
        var7 = ((long (*)(long, long))(*(long *)(&local_20[0])))(*(long *)((&local_20[0] + 8)), (unsigned long)((unsigned int)(i)));
        total = (var7 + total);
    }
    local_4 = total;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
mixed_capture pass 28 lines
// glaurung: mixed_capture @ 0x12a0
__attribute__((no_stack_protector)) int32_t mixed_capture(int32_t arg0, int32_t arg1) {
    extern void _ZZ13mixed_captureENK3__3clEi(char *, int);
    unsigned char total[4];
    int i;
    unsigned char local_20[16];
    int local_4;
    // x86-64 prologue: save rbp, frame 48 bytes
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    *(int *)(&total[0]) = 0;
    *(int *)(&local_20[0]) = arg0;
    *(long *)((&local_20[0] + 8)) = (long)((long)(&total[0]));
    for (i = 0; (i < arg1); i++) {
        _ZZ13mixed_captureENK3__3clEi((char *)(&local_20[0]), (unsigned long)((unsigned int)(i)));
    }
    local_4 = *(int *)(&total[0]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
plain_call_control pass 27 lines
// glaurung: plain_call_control @ 0x1400
int32_t plain_call_control(int32_t arg0, int32_t arg1) {
    extern int _ZL14add_base_plainii(int, int);
    int total;
    int i;
    int local_4;
    int var1;
    // x86-64 prologue: save rbp, frame 32 bytes
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    total = 0;
    for (i = 0; (i < arg1); i++) {
        var1 = _ZL14add_base_plainii((unsigned long)((unsigned int)(i)), (unsigned long)((unsigned int)(arg0)));
        total = (var1 + total);
    }
    local_4 = total;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

gcc -O0

5/6
capture_by_reference pass 27 lines
// glaurung: capture_by_reference @ 0x11de
int32_t capture_by_reference(int32_t arg0) {
    extern void _ZZ20capture_by_referenceENKUliE_clEi(char *, int);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char total[8];
    int i;
    unsigned char local_10[8];
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    if ((((long)(arg0) < 0) || (((unsigned long)((unsigned int)(arg0)) != 32) && (32 <= (long)(arg0))))) {
        ret = 0xffffffff;
    } else {
        *(int *)(&total[0]) = 0;
        *(long *)(&local_10[0]) = (long)((long)(&total[0]));
        for (i = 0; (i < arg0); i++) {
            _ZZ20capture_by_referenceENKUliE_clEi((char *)(&local_10[0]), (unsigned long)((unsigned int)(i)));
        }
        ret = (unsigned long)((unsigned int)(*(int *)(&total[0])));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
capture_by_value pass 29 lines
// glaurung: capture_by_value @ 0x1132
int32_t capture_by_value(int32_t arg0, int32_t arg1) {
    extern int _ZZ16capture_by_valueENKUliE_clEi(char *, int);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int total;
    int i;
    unsigned char local_14[4];
    long local_8;
    long ret;
    int var7;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    if ((((long)(arg1) < 0) || (((unsigned long)((unsigned int)(arg1)) != 32) && (32 <= (long)(arg1))))) {
        ret = 0xffffffff;
    } else {
        *(int *)(&local_14[0]) = arg0;
        total = 0;
        for (i = 0; (i < arg1); i++) {
            var7 = _ZZ16capture_by_valueENKUliE_clEi((char *)(&local_14[0]), (unsigned long)((unsigned int)(i)));
            total = (total + var7);
        }
        ret = (unsigned long)((unsigned int)(total));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
capture_then_mutate pass 20 lines
// glaurung: capture_then_mutate @ 0x1276
int32_t capture_then_mutate(int32_t arg0) {
    extern int _ZZ19capture_then_mutateENKUliE_clEi(char *, int);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    long local_8;
    unsigned char local_c[4];
    long ret;
    int var5;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_8 = (long)(0x28);
    *(int *)(&local_c[0]) = arg0;
    arg0 = (arg0 + 1000);
    var5 = _ZZ19capture_then_mutateENKUliE_clEi((char *)(&local_c[0]), 1);
    ret = (unsigned long)((unsigned int)((var5 + (unsigned long)((unsigned int)(arg0)))));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
erased_callable fail 33 lines
// glaurung: erased_callable @ 0x13a1
int32_t erased_callable(int32_t arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int total;
    int i;
    unsigned char local_20[16];
    unsigned char local_2c[4];
    long local_8;
    long ret;
    long var12;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    if ((((long)(arg1) < 0) || (((unsigned long)((unsigned int)(arg1)) != 32) && (32 <= (long)(arg1))))) {
        ret = 0xffffffff;
    } else {
        *(int *)(&local_2c[0]) = ((unsigned long)((unsigned int)(arg0)) & 7);
        *(long *)(&local_20[0]) = 0;
        *(long *)((&local_20[0] + 8)) = 0;
        *(long *)(&local_20[0]) = (long)((long)(0x1386));
        *(long *)((&local_20[0] + 8)) = (long)((long)(&local_2c[0]));
        total = 0;
        for (i = 0; (i < arg1); i++) {
            var12 = ((long (*)(long, long))(*(long *)(&local_20[0])))(*(long *)((&local_20[0] + 8)), (unsigned long)((unsigned int)(i)));
            total = (total + var12);
        }
        ret = (unsigned long)((unsigned int)(total));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
mixed_capture pass 28 lines
// glaurung: mixed_capture @ 0x12fe
int32_t mixed_capture(int32_t arg0, int32_t arg1) {
    extern void _ZZ13mixed_captureENKUliE_clEi(char *, int);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char total[8];
    int i;
    unsigned char local_20[16];
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    if ((((long)(arg1) < 0) || (((unsigned long)((unsigned int)(arg1)) != 32) && (32 <= (long)(arg1))))) {
        ret = 0xffffffff;
    } else {
        *(int *)(&total[0]) = 0;
        *(int *)(&local_20[0]) = arg0;
        *(long *)((&local_20[0] + 8)) = (long)((long)(&total[0]));
        for (i = 0; (i < arg1); i++) {
            _ZZ13mixed_captureENKUliE_clEi((char *)(&local_20[0]), (unsigned long)((unsigned int)(i)));
        }
        ret = (unsigned long)((unsigned int)(*(int *)(&total[0])));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
plain_call_control pass 23 lines
// glaurung: plain_call_control @ 0x1463
int32_t plain_call_control(int32_t arg0, int32_t arg1) {
    extern int _ZL14add_base_plainii(int, int);
    int total;
    int i;
    int var3;
    // x86-64 prologue: save rbp, frame 24 bytes
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    total = 0;
    for (i = 0; (i < arg1); i++) {
        var3 = _ZL14add_base_plainii((unsigned long)((unsigned int)(i)), (unsigned long)((unsigned int)(arg0)));
        total = (total + var3);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(total);
}

clang -O2

6/6
capture_by_reference pass 13 lines
// glaurung: capture_by_reference @ 0x1130
int32_t capture_by_reference(int32_t arg0) {
    int i;
    long ret;
    ret = 0xffffffff;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 0;
    }
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 - 2))) * (unsigned long)((unsigned int)((arg0 - 1)))))) & -2))) + (arg0 * 2)))) - 2));
}
capture_by_value pass 16 lines
// glaurung: capture_by_value @ 0x1100
int32_t capture_by_value(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long ret;
    long var1;
    ret = 0xffffffff;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)((arg1 - 1)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + 1))) * var1))) + arg0))) + ((unsigned long)(((unsigned long)((unsigned int)((arg1 - 2))) * var1)) >> 1)));
}
capture_then_mutate pass 4 lines
// glaurung: capture_then_mutate @ 0x1160
int32_t capture_then_mutate(int32_t arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) + 1001));
}
erased_callable pass 14 lines
// glaurung: erased_callable @ 0x11a0
int32_t erased_callable(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long ret;
    ret = 0xffffffff;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((((unsigned long)(((unsigned long)((unsigned int)((arg1 - 2))) * (unsigned long)((unsigned int)((arg1 - 1))))) >> 1) + arg1))) - 1))) * (unsigned long)((unsigned int)((arg0 & 7)))));
}
mixed_capture pass 13 lines
// glaurung: mixed_capture @ 0x1170
int32_t mixed_capture(int32_t arg0, int32_t arg1) {
    int i;
    long ret;
    ret = 0xffffffff;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((((unsigned long)(((unsigned long)((unsigned int)((arg1 - 2))) * (unsigned long)((unsigned int)((arg1 - 1))))) >> 1) + arg1))) - 1))) * arg0));
}
plain_call_control pass 16 lines
// glaurung: plain_call_control @ 0x11d0
int32_t plain_call_control(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long ret;
    long var1;
    ret = 0xffffffff;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)((arg1 - 1)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + 1))) * var1))) + arg0))) + ((unsigned long)(((unsigned long)((unsigned int)((arg1 - 2))) * var1)) >> 1)));
}

gcc -O2

6/6
capture_by_reference pass 33 lines
// glaurung: capture_by_reference @ 0x1140
int32_t capture_by_reference(int32_t arg0) {
    int total;
    int i;
    long var1;
    long var3;
    long var6;
    int var8;
    long var9;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
        goto L_1177;
    }
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        goto L_1170;
    }
    var1 = (unsigned long)((unsigned int)((arg0 + arg0)));
    var3 = 0;
    var6 = 0;
    do {
        total = (var6 + var3);
        var6 = (unsigned long)((unsigned int)(total));
        var8 = (var3 + 2);
        var3 = (unsigned long)((unsigned int)(var8));
        var9 = (unsigned long)((unsigned int)(total));
    } while (((unsigned int)(var1) != (unsigned int)(var8)));
    L_1162: ;
    return (unsigned int)(var9);
    L_1170: ;
    return 0;
    L_1177: ;
    var9 = 0xffffffff;
    goto L_1162;
}
capture_by_value pass 24 lines
// glaurung: capture_by_value @ 0x1100
int32_t capture_by_value(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long ret;
    long var2;
    long var5;
    int var7;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (unsigned long)((unsigned int)((arg1 + arg0)));
    ret = 0;
    var5 = (unsigned long)((unsigned int)(arg0));
    do {
        ret = (unsigned long)((unsigned int)((ret + var5)));
        var7 = (var5 + 1);
        var5 = (unsigned long)((unsigned int)(var7));
    } while (((unsigned int)(var2) != (unsigned int)(var7)));
    return ret;
}
capture_then_mutate pass 4 lines
// glaurung: capture_then_mutate @ 0x1180
int32_t capture_then_mutate(int32_t arg0) {
    return (unsigned int)(((arg0 + arg0) + 1001));
}
erased_callable pass 35 lines
// glaurung: erased_callable @ 0x11d0
int32_t erased_callable(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long var1;
    int var10;
    long var13;
    long var3;
    long var8;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_1207;
    }
    var1 = (unsigned long)((unsigned int)((arg0 & 7)));
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_1200;
    }
    var3 = 0;
    var8 = 0;
    i = 0;
    do {
        var10 = (i + 1);
        i = (unsigned long)((unsigned int)(var10));
        total = (var8 + var3);
        var8 = (unsigned long)((unsigned int)(total));
        var3 = (unsigned long)((unsigned int)((var3 + var1)));
        var13 = (unsigned long)((unsigned int)(total));
    } while (((unsigned int)(arg1) != (unsigned int)(var10)));
    L_11fc: ;
    return (unsigned int)(var13);
    L_1200: ;
    return 0;
    L_1207: ;
    var13 = 0xffffffff;
    goto L_11fc;
}
mixed_capture pass 33 lines
// glaurung: mixed_capture @ 0x1190
int32_t mixed_capture(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long var1;
    long var11;
    long var6;
    int var8;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_11c7;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_11c0;
    }
    var1 = 0;
    var6 = 0;
    i = 0;
    do {
        var8 = (i + 1);
        i = (unsigned long)((unsigned int)(var8));
        total = (var6 + var1);
        var6 = (unsigned long)((unsigned int)(total));
        var1 = (unsigned long)((unsigned int)((var1 + arg0)));
        var11 = (unsigned long)((unsigned int)(total));
    } while (((unsigned int)(arg1) != (unsigned int)(var8)));
    L_11b4: ;
    return (unsigned int)(var11);
    L_11c0: ;
    return 0;
    L_11c7: ;
    var11 = 0xffffffff;
    goto L_11b4;
}
plain_call_control pass 24 lines
// glaurung: plain_call_control @ 0x1210
int32_t plain_call_control(int32_t arg0, int32_t arg1) {
    int i;
    int total;
    long ret;
    long var2;
    long var5;
    int var7;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (unsigned long)((unsigned int)((arg1 + arg0)));
    ret = 0;
    var5 = (unsigned long)((unsigned int)(arg0));
    do {
        ret = (unsigned long)((unsigned int)((ret + var5)));
        var7 = (var5 + 1);
        var5 = (unsigned long)((unsigned int)(var7));
    } while (((unsigned int)(var2) != (unsigned int)(var7)));
    return ret;
}

← 213 fixtures