Fixture 189

effectful select

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

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

A call with a side effect, sitting inside a conditional select.

lazy_call_select and copy_prop::move_adjacent_effectful_scratch_values fold a diamond into a ternary. That is only sound if the folded call is evaluated exactly as often as the machine evaluated it. A fold that hoists the call above the condition, or that duplicates it into both arms, still produces plausible C with the right RETURN VALUE — the arithmetic is unchanged — and is caught only by counting the effect.

This is the same soundness class as the vector-transport bug in 188: one value with more than one consumer, where the transform assumed exactly one. There the second consumer read undefined lanes; here the effect count moves.

The count is kept in the caller's own buffer rather than a global, so it survives the harness rebuilding a single function against extern callees, and so the differential observes it directly.

se189_select_pure is the control: no call in either arm, so folding is entirely correct and must still happen. A fixture that only forbids folding would be satisfied by a decompiler that never folds anything.

tests/decompiler_fixtures/src/189_effectful_select.c source
#include <stdint.h>

/* A call with a side effect, sitting inside a conditional select.
 *
 * `lazy_call_select` and `copy_prop::move_adjacent_effectful_scratch_values`
 * fold a diamond into a ternary. That is only sound if the folded call is
 * evaluated exactly as often as the machine evaluated it. A fold that hoists
 * the call above the condition, or that duplicates it into both arms, still
 * produces plausible C with the right RETURN VALUE — the arithmetic is
 * unchanged — and is caught only by counting the effect.
 *
 * This is the same soundness class as the vector-transport bug in `188`: one
 * value with more than one consumer, where the transform assumed exactly one.
 * There the second consumer read undefined lanes; here the effect count moves.
 *
 * The count is kept in the caller's own buffer rather than a global, so it
 * survives the harness rebuilding a single function against extern callees,
 * and so the differential observes it directly.
 *
 * `se189_select_pure` is the control: no call in either arm, so folding is
 * entirely correct and must still happen. A fixture that only forbids folding
 * would be satisfied by a decompiler that never folds anything. */

#define SE189_SLOT_SELECTED 1
#define SE189_SLOT_WITNESS 2

__attribute__((noinline)) int32_t se189_bump(int32_t *calls, int32_t value) {
    if (calls == 0) {
        return -1;
    }
    calls[0] += 1;
    return value * 2 + 1;
}

__attribute__((noinline)) int32_t se189_select_call(int32_t *scratch, int32_t flag,
                                                    int32_t a, int32_t b) {
    int32_t selected;
    if (scratch == 0) {
        return -1;
    }
    scratch[0] = 0;
    /* Exactly one of these calls happens. If a fold evaluates both, or hoists
     * one above the branch, scratch[0] becomes 2 and the differential fails
     * even though the returned value is identical. */
    selected = flag ? se189_bump(scratch, a) : se189_bump(scratch, b);
    scratch[SE189_SLOT_SELECTED] = selected;
    scratch[SE189_SLOT_WITNESS] = scratch[0];
    return selected;
}

__attribute__((noinline)) int32_t se189_select_one_arm(int32_t *scratch, int32_t flag,
                                                       int32_t a, int32_t b) {
    int32_t selected;
    if (scratch == 0) {
        return -1;
    }
    scratch[0] = 0;
    /* Asymmetric: only the taken arm may call. Speculating the call so both
     * arms share one evaluation changes the count on the `b` path. */
    selected = flag ? se189_bump(scratch, a) : b;
    scratch[SE189_SLOT_SELECTED] = selected;
    scratch[SE189_SLOT_WITNESS] = scratch[0];
    return selected;
}

__attribute__((noinline)) int32_t se189_nested_select(int32_t *scratch, int32_t first,
                                                      int32_t second, int32_t a,
                                                      int32_t b) {
    int32_t selected;
    if (scratch == 0) {
        return -1;
    }
    scratch[0] = 0;
    /* Nested diamonds: at most one call on any path through both conditions. */
    selected = first ? (second ? se189_bump(scratch, a) : a) : (second ? b : se189_bump(scratch, b));
    scratch[SE189_SLOT_SELECTED] = selected;
    scratch[SE189_SLOT_WITNESS] = scratch[0];
    return selected;
}

__attribute__((noinline)) int32_t se189_select_pure(int32_t *scratch, int32_t flag,
                                                    int32_t a, int32_t b) {
    int32_t selected;
    if (scratch == 0) {
        return -1;
    }
    scratch[0] = 0;
    /* CONTROL: no call in either arm, so this diamond SHOULD fold to a ternary.
     * Present so the fixture cannot be satisfied by refusing to fold at all. */
    selected = flag ? (a * 2 + 1) : (b * 2 + 1);
    scratch[SE189_SLOT_SELECTED] = selected;
    scratch[SE189_SLOT_WITNESS] = scratch[0];
    return selected;
}

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
se189_bump pass 10 lines
// glaurung: se189_bump @ 0x1110
int32_t se189_bump(int32_t * arg0, int32_t arg1) {
    // x86-64 prologue: save rbp
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = ((unsigned long)((unsigned int)(*(int *)((long)arg0))) + 1);
        return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) << 1))) + 1));
    } else {
        return (unsigned int)(-1);
    }
}
se189_nested_select pass 37 lines
// glaurung: se189_nested_select @ 0x1270
int32_t se189_nested_select(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
    extern int se189_bump(int *, int);
    int selected;
    int local_28;
    int local_2c;
    int local_30;
    int var1;
    int var6;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            if (((unsigned long)((unsigned int)(arg2)) == 0)) {
                var1 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg4)));
                local_30 = var1;
            } else {
                local_30 = arg4;
            }
            local_2c = local_30;
        } else {
            if (((unsigned long)((unsigned int)(arg2)) == 0)) {
                local_28 = arg3;
            } else {
                var6 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
                local_28 = var6;
            }
            local_2c = local_28;
        }
        selected = local_2c;
        *(int *)(((long)arg0 + 0x4)) = selected;
        *(int *)(((long)arg0 + 0x8)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return (unsigned int)(-1);
    }
}
se189_select_call pass 25 lines
// glaurung: se189_select_call @ 0x1150
int32_t se189_select_call(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    int local_24;
    int var1;
    int var3;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            var1 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
            local_24 = var1;
        } else {
            var3 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg2)));
            local_24 = var3;
        }
        selected = local_24;
        *(int *)(((long)arg0 + 0x4)) = selected;
        *(int *)(((long)arg0 + 0x8)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return (unsigned int)(-1);
    }
}
se189_select_one_arm pass 23 lines
// glaurung: se189_select_one_arm @ 0x11e0
int32_t se189_select_one_arm(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    int local_24;
    int var2;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            local_24 = arg3;
        } else {
            var2 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg2)));
            local_24 = var2;
        }
        selected = local_24;
        *(int *)(((long)arg0 + 0x4)) = selected;
        *(int *)(((long)arg0 + 0x8)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return (unsigned int)(-1);
    }
}
se189_select_pure pass 16 lines
// glaurung: se189_select_pure @ 0x1340
int32_t se189_select_pure(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int selected;
    int local_24;
    // x86-64 prologue: save rbp
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        local_24 = (((unsigned long)((unsigned int)(arg1)) == 0) ? ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) << 1))) + 1) : ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) << 1))) + 1));
        selected = local_24;
        *(int *)(((long)arg0 + 0x4)) = selected;
        *(int *)(((long)arg0 + 0x8)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return (unsigned int)(-1);
    }
}

clang -O2

5/5
se189_bump pass 8 lines
// glaurung: se189_bump @ 0x1110
int32_t se189_bump(int32_t * arg0, int32_t arg1) {
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg0)) = (*(int *)(((long)arg0)) + 1);
    return (unsigned int)(((unsigned long)((unsigned int)((arg1 + arg1))) + 1));
}
se189_nested_select pass 38 lines
// glaurung: se189_nested_select @ 0x11a0
int32_t se189_nested_select(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
    extern int se189_bump(int *, int);
    int selected;
    long var0;
    long var1;
    int var2;
    if ((arg0 == 0)) {
        goto L_11cd;
    }
    var0 = (long)arg0;
    *(int *)(((long)arg0)) = 0;
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_11d3;
    }
    var1 = (unsigned long)((unsigned int)(arg3));
    selected = (unsigned long)((unsigned int)(arg3));
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        goto L_11c3;
    }
    L_11b9: ;
    var2 = se189_bump((int *)(var0), (unsigned long)((unsigned int)(var1)));
    selected = (unsigned long)((unsigned int)(var2));
    L_11c3: ;
    *(int *)((var0 + 0x4)) = selected;
    *(int *)((var0 + 0x8)) = *(int *)((var0));
    // x86-64 epilogue: tear down frame
    return selected;
    L_11cd: ;
    return 0xffffffff;
    L_11d3: ;
    var1 = (unsigned long)((unsigned int)(arg4));
    selected = (unsigned long)((unsigned int)(arg4));
    if (((unsigned long)((unsigned int)(arg2)) != 0)) {
        goto L_11c3;
    }
    goto L_11b9;
}
se189_select_call pass 17 lines
// glaurung: se189_select_call @ 0x1130
int32_t se189_select_call(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    int ret;
    long var0;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var0 = (long)arg0;
    *(int *)(((long)arg0)) = 0;
    ret = se189_bump((int *)(arg0), (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(arg1)) == 0) ? arg3 : arg2))));
    *(int *)((var0 + 0x4)) = ret;
    *(int *)((var0 + 0x8)) = *(int *)((var0));
    // x86-64 epilogue: tear down frame
    return ret;
}
se189_select_one_arm pass 25 lines
// glaurung: se189_select_one_arm @ 0x1160
int32_t se189_select_one_arm(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    long var0;
    long var3;
    int var4;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var0 = (long)arg0;
    *(int *)(((long)arg0)) = 0;
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var3 = 0;
        selected = (unsigned long)((unsigned int)(arg3));
    } else {
        var4 = se189_bump((int *)(var0), (unsigned long)((unsigned int)(arg2)));
        var3 = (unsigned long)((unsigned int)(*(int *)((var0))));
        selected = (unsigned long)((unsigned int)(var4));
    }
    *(int *)((var0 + 0x4)) = selected;
    *(int *)((var0 + 0x8)) = var3;
    // x86-64 epilogue: tear down frame
    return selected;
}
se189_select_pure pass 15 lines
// glaurung: se189_select_pure @ 0x11e0
int32_t se189_select_pure(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int selected;
    long var0;
    int var2;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var0 = (((unsigned long)((unsigned int)(arg1)) == 0) ? arg3 : arg2);
    *(int *)(((long)arg0)) = 0;
    var2 = ((unsigned int)((var0 + var0)) + 1);
    *(int *)(((long)arg0 + 0x4)) = var2;
    *(int *)(((long)arg0 + 0x8)) = 0;
    return (unsigned int)(var2);
}

gcc -O0

5/5
se189_bump pass 10 lines
// glaurung: se189_bump @ 0x1119
int32_t se189_bump(int32_t * arg0, int32_t arg1) {
    // x86-64 prologue: save rbp
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = ((unsigned long)((unsigned int)(*(int *)((long)arg0))) + 1);
        return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) + (unsigned long)((unsigned int)(arg1))))) + 1));
    } else {
        return 0xffffffff;
    }
}
se189_nested_select pass 33 lines
// glaurung: se189_nested_select @ 0x1241
int32_t se189_nested_select(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
    extern int se189_bump(int *, int);
    int selected;
    long var1;
    int var4;
    int var7;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            if (((unsigned long)((unsigned int)(arg2)) != 0)) {
                var1 = (unsigned long)((unsigned int)(arg4));
            } else {
                var4 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg4)));
                var1 = (unsigned long)((unsigned int)(var4));
            }
        } else {
            if (((unsigned long)((unsigned int)(arg2)) == 0)) {
                var1 = (unsigned long)((unsigned int)(arg3));
            } else {
                var7 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
                var1 = (unsigned long)((unsigned int)(var7));
            }
        }
        selected = var1;
        *(int *)((arg0 + 1)) = selected;
        *(int *)((arg0 + 2)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return 0xffffffff;
    }
}
se189_select_call pass 25 lines
// glaurung: se189_select_call @ 0x114f
int32_t se189_select_call(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    int var3;
    long var4;
    int var7;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            var3 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
            var4 = (unsigned long)((unsigned int)(var3));
        } else {
            var7 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg2)));
            var4 = (unsigned long)((unsigned int)(var7));
        }
        selected = var4;
        *(int *)((arg0 + 1)) = selected;
        *(int *)((arg0 + 2)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return 0xffffffff;
    }
}
se189_select_one_arm pass 23 lines
// glaurung: se189_select_one_arm @ 0x11cf
int32_t se189_select_one_arm(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    long var1;
    int var4;
    // x86-64 prologue: save rbp, frame 48 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            var1 = (unsigned long)((unsigned int)(arg3));
        } else {
            var4 = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg2)));
            var1 = (unsigned long)((unsigned int)(var4));
        }
        selected = var1;
        *(int *)((arg0 + 1)) = selected;
        *(int *)((arg0 + 2)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return 0xffffffff;
    }
}
se189_select_pure pass 14 lines
// glaurung: se189_select_pure @ 0x12db
int32_t se189_select_pure(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int selected;
    // x86-64 prologue: save rbp
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = 0;
        selected = (((unsigned long)((unsigned int)(arg1)) == 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) + (unsigned long)((unsigned int)(arg3))))) + 1))) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) + (unsigned long)((unsigned int)(arg2))))) + 1))));
        *(int *)((arg0 + 1)) = selected;
        *(int *)((arg0 + 2)) = *(int *)((long)arg0);
        return (unsigned int)(selected);
    } else {
        return 0xffffffff;
    }
}

gcc -O2

5/5
se189_bump pass 8 lines
// glaurung: se189_bump @ 0x1120
int32_t se189_bump(int32_t * arg0, int32_t arg1) {
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg0)) = (*(int *)(((long)arg0)) + 1);
    return (unsigned int)(((arg1 + arg1) + 1));
}
se189_nested_select pass 50 lines
// glaurung: se189_nested_select @ 0x11d0
int32_t se189_nested_select(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
    extern int se189_bump(int *, int);
    int selected;
    long local_8;
    int ret;
    long var0;
    long var1;
    long var11;
    long var3;
    long var8;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    local_8 = var0;
    var1 = (long)arg0;
    *(int *)(((long)arg0)) = 0;
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        goto L_1200;
    }
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        goto L_1220;
    }
    var3 = 0;
    ret = (unsigned long)((unsigned int)(arg4));
    L_11f0: ;
    *(int *)((var1 + 0x4)) = ret;
    *(int *)((var1 + 0x8)) = var3;
    // x86-64 epilogue: tear down frame
    return ret;
    L_1200: ;
    ret = (unsigned long)((unsigned int)(arg3));
    var3 = (unsigned long)((unsigned int)(arg2));
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        goto L_11f0;
    }
    ret = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
    var8 = (unsigned long)((unsigned int)(*(int *)((var1))));
    *(int *)((var1 + 0x4)) = ret;
    *(int *)((var1 + 0x8)) = var8;
    // x86-64 epilogue: tear down frame
    return ret;
    L_1220: ;
    ret = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg4)));
    var11 = (unsigned long)((unsigned int)(*(int *)((var1))));
    *(int *)((var1 + 0x4)) = ret;
    *(int *)((var1 + 0x8)) = var11;
    // x86-64 epilogue: tear down frame
    return ret;
}
se189_select_call pass 31 lines
// glaurung: se189_select_call @ 0x1140
int32_t se189_select_call(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    long local_8;
    int ret;
    long var0;
    long var1;
    long var3;
    long var6;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    local_8 = var0;
    var1 = (long)arg0;
    *(int *)(((long)arg0)) = 0;
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        ret = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg2)));
        var3 = (unsigned long)((unsigned int)(*(int *)((var1))));
        *(int *)((var1 + 0x4)) = ret;
        *(int *)((var1 + 0x8)) = var3;
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = se189_bump((int *)(arg0), (unsigned long)((unsigned int)(arg3)));
    var6 = (unsigned long)((unsigned int)(*(int *)((var1))));
    *(int *)((var1 + 0x4)) = ret;
    *(int *)((var1 + 0x8)) = var6;
    // x86-64 epilogue: tear down frame
    return ret;
}
se189_select_one_arm pass 28 lines
// glaurung: se189_select_one_arm @ 0x1190
int32_t se189_select_one_arm(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern int se189_bump(int *, int);
    int selected;
    long local_8;
    long var0;
    long var1;
    long var3;
    int var5;
    local_8 = var0;
    var1 = (long)arg0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    *(int *)((var1)) = 0;
    var3 = (unsigned long)((unsigned int)(arg1));
    selected = (unsigned long)((unsigned int)(arg3));
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        var5 = se189_bump((int *)(var1), (unsigned long)((unsigned int)(arg2)));
        var3 = (unsigned long)((unsigned int)(*(int *)((var1))));
        selected = (unsigned long)((unsigned int)(var5));
    }
    *(int *)((var1 + 0x4)) = selected;
    *(int *)((var1 + 0x8)) = var3;
    // x86-64 epilogue: tear down frame
    return selected;
}
se189_select_pure pass 18 lines
// glaurung: se189_select_pure @ 0x1240
int32_t se189_select_pure(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    int selected;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg0)) = 0;
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        selected = (unsigned long)((unsigned int)(((arg2 + arg2) + 1)));
        *(int *)(((long)arg0 + 0x8)) = 0;
        *(int *)(((long)arg0 + 0x4)) = selected;
        return selected;
    }
    selected = (unsigned long)((unsigned int)(((arg3 + arg3) + 1)));
    *(int *)(((long)arg0 + 0x8)) = 0;
    *(int *)(((long)arg0 + 0x4)) = selected;
    return selected;
}

← 213 fixtures