Fixture 201

float bit stores

C · 8 functions · 4 lanes · 25 of 32 function-lanes behave identically

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

A FLOATING VALUE STORED THROUGH INTEGER-TYPED STORAGE, and the reverse.

movss %xmm0, -0x10(%rbp) copies four bytes. The recovered destination type comes from the ACCESS WIDTH, so it is int, and a renderer that reconciles an int destination with a float source by inserting a cast emits *(int *)(&local[0]) = (float)(...) — which is C's arithmetic conversion (C23 6.3.1.4, truncation toward zero). 1.5f is then written as 1 rather than 0x3FC00000, and every byte of the destination is wrong immediately, before anything downstream reads it.

The corpus already contained this shape in 195, 197 and 198 — but only inside AGGREGATE-RETURNING helpers, which exec_class refuses, so all twelve occurrences were recorded structural and none was ever executed. It also contained it in 174's fp174_float_bits, which is a LOCAL symbol with no baseline row of its own. So the defect had no lane that could report it: no function in the corpus both exhibits the shape and is directly executed. Every function here is int32_t-returning and scalar-argument, so every one of them is.

THE NEGATIVE CONTROLS ARE THE POINT. A reinterpretation is right here and wrong for cvttss2si, and the two are one instruction apart. f201_*_values do the same arithmetic on the same values and TRUNCATE, so a recovery that satisfies the positives by never converting fails exactly there; and f201_scalar_control has no floating point at all, so a recovery that broke ordinary integer stores while fixing these is separable from one that did not.

memcpy rather than a union or a pointer cast: it is the one spelling defined under every aliasing rule, and both compilers turn a four- or eight-byte copy into a single register move. Every value is a small integer converted to float/double, so it is exactly representable in both widths and the differential compares exact values rather than rounding artifacts.

tests/decompiler_fixtures/src/201_float_bit_stores.c source
#include <stdint.h>
#include <string.h>

/* A FLOATING VALUE STORED THROUGH INTEGER-TYPED STORAGE, and the reverse.
 *
 * `movss %xmm0, -0x10(%rbp)` copies four bytes. The recovered destination type
 * comes from the ACCESS WIDTH, so it is `int`, and a renderer that reconciles
 * an `int` destination with a `float` source by inserting a cast emits
 * `*(int *)(&local[0]) = (float)(...)` — which is C's arithmetic conversion
 * (C23 6.3.1.4, truncation toward zero). `1.5f` is then written as `1` rather
 * than `0x3FC00000`, and every byte of the destination is wrong immediately,
 * before anything downstream reads it.
 *
 * The corpus already contained this shape in `195`, `197` and `198` — but only
 * inside AGGREGATE-RETURNING helpers, which `exec_class` refuses, so all twelve
 * occurrences were recorded `structural` and none was ever executed. It also
 * contained it in `174`'s `fp174_float_bits`, which is a LOCAL symbol with no
 * baseline row of its own. So the defect had no lane that could report it: no
 * function in the corpus both exhibits the shape and is directly executed.
 * Every function here is `int32_t`-returning and scalar-argument, so every one
 * of them is.
 *
 * THE NEGATIVE CONTROLS ARE THE POINT. A reinterpretation is right here and
 * wrong for `cvttss2si`, and the two are one instruction apart. `f201_*_values`
 * do the same arithmetic on the same values and TRUNCATE, so a recovery that
 * satisfies the positives by never converting fails exactly there; and
 * `f201_scalar_control` has no floating point at all, so a recovery that broke
 * ordinary integer stores while fixing these is separable from one that did not.
 *
 * `memcpy` rather than a union or a pointer cast: it is the one spelling
 * defined under every aliasing rule, and both compilers turn a four- or
 * eight-byte copy into a single register move. Every value is a small integer
 * converted to `float`/`double`, so it is exactly representable in both widths
 * and the differential compares exact values rather than rounding artifacts. */

#define F201_SLOTS 2

/* ---- positives: a float's BITS reach an integer destination ---------------- */

/* The reported shape at binary32. At `-O0` both compilers emit
 * `cvtsi2ss ... ; movss %xmm0, -N(%rbp)` for each slot and then read the same
 * bytes back with an integer `mov`. The exponent fields are the part a
 * truncating conversion destroys: `(float)(seed + 1)` for a small `seed` has
 * bits around 0x4000_0000 and a value around 1, so the two disagree in every
 * bit that this function returns. */
__attribute__((noinline)) int32_t f201_f32_slot_bits(int32_t seed) {
    float slots[F201_SLOTS];
    uint32_t words[F201_SLOTS];
    slots[0] = (float)(seed + 1);
    slots[1] = (float)(seed * 2 + 3);
    memcpy(words, slots, sizeof words);
    /* Distinct coefficients, so recovering the right total from permuted or
     * duplicated slots is caught rather than passing by luck. */
    return (int32_t)((words[0] >> 23) * 3u + (words[1] >> 20) * 5u);
}

/* The same at binary64, which is a different instruction (`movsd`), a different
 * access width, and a different recovered pointee (`long`, not `int`). */
__attribute__((noinline)) int32_t f201_f64_slot_bits(int32_t seed) {
    double slots[F201_SLOTS];
    uint64_t words[F201_SLOTS];
    slots[0] = (double)(seed + 1);
    slots[1] = (double)(seed * 2 + 3);
    memcpy(words, slots, sizeof words);
    return (int32_t)((uint32_t)(words[0] >> 52) * 3u + (uint32_t)(words[1] >> 48) * 5u);
}

/* The single-value form, with no array indexing between the store and the read.
 * This is `174`'s `fp174_float_bits` promoted to an exported, executable
 * function: the whole body is one `movss` to the frame and one `mov` back. */
__attribute__((noinline)) int32_t f201_f32_single_bits(int32_t seed) {
    float value = (float)(seed * 4 + 1);
    uint32_t word;
    memcpy(&word, &value, sizeof word);
    return (int32_t)(word >> 16);
}

/* Through a CALLER-OWNED pointer rather than a frame slot, so the destination
 * is not a promoted local and the store cannot be recovered as a plain
 * variable assignment. */
__attribute__((noinline)) int32_t f201_store_through_pointer(int32_t *out, int32_t seed) {
    float value = (float)(seed + 7);
    if (out == 0) {
        return -1;
    }
    memcpy(out, &value, sizeof *out);
    return (int32_t)(((uint32_t)*out) >> 21);
}

/* ---- the mirror: an integer bit pattern read back as a float --------------- */

/* `word` is built with a pinned exponent field, so `value` is finite, normal
 * and inside [8, 16) for every input the harness can draw — the multiply and
 * the truncation below are therefore defined for all of them, and a NaN or an
 * out-of-range conversion can never be reached. */
__attribute__((noinline)) int32_t f201_word_to_value(int32_t seed) {
    uint32_t word = 0x41000000u | (((uint32_t)seed & 0x7Fu) << 8);
    float value;
    memcpy(&value, &word, sizeof value);
    return (int32_t)(value * 256.0f);
}

/* ---- negative controls: conversions that must stay conversions ------------- */

/* THE FIRST NEGATIVE. Identical storage, identical arithmetic, but the slots
 * are read as NUMBERS. `cvttss2si` truncates toward zero, and a recovery that
 * reinterpreted every float reaching an integer destination would return the
 * exponent fields here instead of the values — off by seven orders of
 * magnitude, not by a rounding step. Bounded well inside the int32 range so no
 * conversion is undefined. */
__attribute__((noinline)) int32_t f201_f32_slot_values(int32_t seed) {
    float slots[F201_SLOTS];
    slots[0] = (float)(seed + 1) / 2.0f;
    slots[1] = (float)(seed * 2 + 3) / 4.0f;
    return (int32_t)slots[0] * 3 + (int32_t)slots[1] * 5;
}

/* THE SECOND NEGATIVE, at binary64 and through a `memcpy` of the FLOAT — the
 * copy is a bit move, the read that follows is a conversion, and both happen in
 * one function. A recovery that decides "this buffer holds bits" or "this
 * buffer holds numbers" once per object rather than once per access is wrong
 * here whichever way it decides. */
__attribute__((noinline)) int32_t f201_f64_copy_then_convert(int32_t seed) {
    double value = (double)(seed * 3 + 1) / 8.0;
    double copy;
    memcpy(&copy, &value, sizeof copy);
    return (int32_t)copy * 7;
}

/* THE THIRD NEGATIVE: the same buffer traffic with no floating point anywhere,
 * so a recovery that damaged ordinary integer stores while fixing the positives
 * fails here and only here. */
__attribute__((noinline)) int32_t f201_scalar_control(int32_t seed) {
    int32_t slots[F201_SLOTS];
    uint32_t words[F201_SLOTS];
    slots[0] = seed + 1;
    slots[1] = seed * 2 + 3;
    memcpy(words, slots, sizeof words);
    return (int32_t)(words[0] * 3u + words[1] * 5u);
}

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.

gcc -O2

5/8
f201_f32_single_bits pass 4 lines
// glaurung: f201_f32_single_bits @ 0x1180
int32_t f201_f32_single_bits(int32_t arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)(((0 + (arg0 * 4)) + 1))))) }).bits)) >> 16));
}
f201_f32_slot_bits pass 8 lines
// glaurung: f201_f32_slot_bits @ 0x1100
int32_t f201_f32_slot_bits(int32_t arg0) {
    long var19;
    long var22;
    var19 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)((arg0 + 1))))) }).bits)) >> 23)));
    var22 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)(((arg0 + arg0) + 3))))) }).bits)) >> 20)));
    return (unsigned int)(((unsigned long)((unsigned int)((var19 + (var19 * 2)))) + (unsigned long)((unsigned int)((var22 + (var22 * 4))))));
}
f201_f32_slot_values fail 11 lines
// glaurung: f201_f32_slot_values @ 0x1200
int32_t f201_f32_slot_values(int32_t arg0) {
    long ret;
    long var11;
    long var20;
    var11 = (int)(((float)((int)((unsigned long)((unsigned int)(((arg0 + arg0) + 3))))) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3e800000) }).value));
    ret = ((union { unsigned int bits; float value; }){ .value = ((float)((int)((unsigned long)((unsigned int)((arg0 + 1))))) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value) }).bits;
    ret = (unsigned long)((unsigned int)((var11 + (var11 * 4))));
    var20 = (int)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(ret) }).value);
    return (unsigned int)((ret + (unsigned long)((unsigned int)((var20 + (var20 * 2))))));
}
f201_f64_copy_then_convert pass 6 lines
// glaurung: f201_f64_copy_then_convert @ 0x1240
int32_t f201_f64_copy_then_convert(int32_t arg0) {
    int var11;
    var11 = (int)(((double)((int)((unsigned long)((unsigned int)(((arg0 + (arg0 * 2)) + 1))))) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3fc0000000000000) }).value));
    return (unsigned int)(((unsigned long)((unsigned int)((var11 * 8))) - var11));
}
f201_f64_slot_bits fail 8 lines
// glaurung: f201_f64_slot_bits @ 0x1140
int32_t f201_f64_slot_bits(int32_t arg0) {
    double var19;
    double var20;
    var19 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(((unsigned long)((double)((int)((unsigned long)((unsigned int)((arg0 + 1)))))) >> 52)) }).value;
    var20 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(((unsigned long)((double)((int)((unsigned long)((unsigned int)(((arg0 + arg0) + 3)))))) >> 48)) }).value;
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = (var19 + (var19 * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(2) }).value)) }).bits)) + (unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = (var20 + (var20 * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(4) }).value)) }).bits))));
}
f201_scalar_control pass 6 lines
// glaurung: f201_scalar_control @ 0x1270
int32_t f201_scalar_control(int32_t arg0) {
    long var0;
    var0 = (unsigned long)((unsigned int)(((arg0 + arg0) + 3)));
    return (unsigned int)(((unsigned long)((unsigned int)(((arg0 + (arg0 * 2)) + 3))) + (unsigned long)((unsigned int)((var0 + (var0 * 4))))));
}
f201_store_through_pointer pass 11 lines
// glaurung: f201_store_through_pointer @ 0x11a0
int32_t f201_store_through_pointer(int32_t * arg0, int32_t arg1) {
    float value;
    float var7;
    var7 = (float)((int)((unsigned long)((unsigned int)((arg1 + 7)))));
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(float *)(((long)arg0)) = var7;
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = var7 }).bits)) >> 21));
}
f201_word_to_value fail 4 lines
// glaurung: f201_word_to_value @ 0x11d0
int32_t f201_word_to_value(int32_t arg0) {
    return ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 << 8))) & 0x7f00))) | 0x41000000))) * 0x43800000);
}

clang -O2

6/8
f201_f32_single_bits pass 6 lines
// glaurung: f201_f32_single_bits @ 0x1160
int32_t f201_f32_single_bits(int32_t arg0) {
    float value;
    unsigned int word;
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)(((0 + (arg0 * 4)) + 1))))) }).bits)) >> 16));
}
f201_f32_slot_bits pass 8 lines
// glaurung: f201_f32_slot_bits @ 0x1100
int32_t f201_f32_slot_bits(int32_t arg0) {
    long var12;
    long var16;
    var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)((arg0 + 1))))) }).bits)) >> 23)));
    var16 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) + 3))))) }).bits)) >> 20)));
    return (unsigned int)(((unsigned long)((unsigned int)((var16 + (var16 * 4)))) + (unsigned long)((unsigned int)((var12 + (var12 * 2))))));
}
f201_f32_slot_values pass 8 lines
// glaurung: f201_f32_slot_values @ 0x11c0
int32_t f201_f32_slot_values(int32_t arg0) {
    int var11;
    int var13;
    var11 = (int)(((float)((int)((unsigned long)((unsigned int)((arg0 + 1))))) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value));
    var13 = (int)(((float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) + 3))))) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3e800000) }).value));
    return (unsigned int)(((unsigned long)((unsigned int)((var13 + (var13 * 4)))) + (unsigned long)((unsigned int)((var11 + (var11 * 2))))));
}
f201_f64_copy_then_convert pass 8 lines
// glaurung: f201_f64_copy_then_convert @ 0x1200
int32_t f201_f64_copy_then_convert(int32_t arg0) {
    double copy;
    double value;
    int var9;
    var9 = (int)(((double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + (arg0 * 2)))) + 1))))) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3fc0000000000000) }).value));
    return (unsigned int)(((unsigned long)((unsigned int)((var9 * 8))) - var9));
}
f201_f64_slot_bits fail 8 lines
// glaurung: f201_f64_slot_bits @ 0x1130
int32_t f201_f64_slot_bits(int32_t arg0) {
    double var11;
    double var13;
    var11 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(((unsigned long)((double)((int)((unsigned long)((unsigned int)((arg0 + 1)))))) >> 52)) }).value;
    var13 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(((unsigned long)((double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) + 3)))))) >> 48)) }).value;
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = (var13 + (var13 * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(4) }).value)) }).bits)) + (unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = (var11 + (var11 * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(2) }).value)) }).bits))));
}
f201_scalar_control pass 4 lines
// glaurung: f201_scalar_control @ 0x1220
int32_t f201_scalar_control(int32_t arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)((arg0 + ((unsigned long)((unsigned int)((arg0 + (arg0 * 2)))) * 4)))) + 18));
}
f201_store_through_pointer pass 11 lines
// glaurung: f201_store_through_pointer @ 0x1180
int32_t f201_store_through_pointer(int32_t * arg0, int32_t arg1) {
    float value;
    float var2;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var2 = (float)((int)((unsigned long)((unsigned int)((arg1 + 7)))));
    *(float *)(((long)arg0)) = var2;
    return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = var2 }).bits)) >> 21));
}
f201_word_to_value fail 6 lines
// glaurung: f201_word_to_value @ 0x11a0
int32_t f201_word_to_value(int32_t arg0) {
    float value;
    unsigned int word;
    return ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 & 127))) << 8))) | 0x41000000))) * 0x43800000);
}

clang -O0

7/8
f201_f32_single_bits pass 10 lines
// glaurung: f201_f32_single_bits @ 0x11b0
int32_t f201_f32_single_bits(int32_t arg0) {
    float value;
    unsigned int word;
    // x86-64 prologue: save rbp
    value = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 2))) + 1)))));
    word = ((union { unsigned int bits; float value; }){ .value = value }).bits;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)(word) >> 16));
}
f201_f32_slot_bits pass 11 lines
// glaurung: f201_f32_slot_bits @ 0x1100
__attribute__((no_stack_protector)) int32_t f201_f32_slot_bits(int32_t arg0) {
    unsigned char local_14[8];
    unsigned char local_c[8];
    // x86-64 prologue: save rbp
    *(float *)(&local_c[0]) = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1)))));
    *(float *)((&local_c[0] + 4)) = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 1))) + 3)))));
    *(long *)(&local_14[0]) = *(long *)(&local_c[0]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_14[0]))) >> 23))) * 3) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_14[0] + 4)))) >> 20))) * 5)));
}
f201_f32_slot_values pass 9 lines
// glaurung: f201_f32_slot_values @ 0x1270
__attribute__((no_stack_protector)) int32_t f201_f32_slot_values(int32_t arg0) {
    unsigned char local_c[8];
    // x86-64 prologue: save rbp
    *(float *)(&local_c[0]) = ((float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1))))) / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40000000) }).value);
    *(float *)((&local_c[0] + 4)) = ((float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 1))) + 3))))) / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40800000) }).value);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((((int)(*(float *)(&local_c[0])) * 3) + ((int)(*(float *)((&local_c[0] + 4))) * 5)));
}
f201_f64_copy_then_convert pass 10 lines
// glaurung: f201_f64_copy_then_convert @ 0x12d0
int32_t f201_f64_copy_then_convert(int32_t arg0) {
    double value;
    double copy;
    // x86-64 prologue: save rbp
    value = ((double)((int)((unsigned long)((unsigned int)(((arg0 * 3) + 1))))) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4020000000000000) }).value);
    copy = value;
    // x86-64 epilogue: restore rbp
    return ((int)(copy) * 7);
}
f201_f64_slot_bits pass 12 lines
// glaurung: f201_f64_slot_bits @ 0x1150
__attribute__((no_stack_protector)) int32_t f201_f64_slot_bits(int32_t arg0) {
    unsigned char local_20[16];
    unsigned char local_30[16];
    // x86-64 prologue: save rbp
    *(double *)(&local_20[0]) = (double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1)))));
    *(double *)((&local_20[0] + 8)) = (double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 1))) + 3)))));
    *(long *)(&local_30[0]) = *(long *)(&local_20[0]);
    *(long *)((&local_30[0] + 8)) = *(long *)((&local_20[0] + 8));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((((unsigned long)(*(long *)(&local_30[0])) >> 52) * 3) + (((unsigned long)(*(long *)((&local_30[0] + 8))) >> 48) * 5)));
}
f201_scalar_control pass 11 lines
// glaurung: f201_scalar_control @ 0x1310
__attribute__((no_stack_protector)) int32_t f201_scalar_control(int32_t arg0) {
    unsigned char local_14[8];
    unsigned char local_c[8];
    // x86-64 prologue: save rbp
    *(int *)(&local_c[0]) = ((unsigned long)((unsigned int)(arg0)) + 1);
    *(int *)((&local_c[0] + 4)) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 1))) + 3);
    *(long *)(&local_14[0]) = *(long *)(&local_c[0]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((*(int *)(&local_14[0]) * 3) + (*(int *)((&local_14[0] + 4)) * 5)));
}
f201_store_through_pointer pass 12 lines
// glaurung: f201_store_through_pointer @ 0x11e0
int32_t f201_store_through_pointer(int32_t * arg0, int32_t arg1) {
    float value;
    // x86-64 prologue: save rbp
    value = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) + 7)))));
    if ((arg0 != 0)) {
        *(float *)((long)arg0) = value;
        return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((long)arg0))) >> 21));
    } else {
        return (unsigned int)(-1);
    }
}
f201_word_to_value fail 10 lines
// glaurung: f201_word_to_value @ 0x1230
int32_t f201_word_to_value(int32_t arg0) {
    unsigned int word;
    float value;
    // x86-64 prologue: save rbp
    word = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 127))) << 8)) | 0x41000000);
    value = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(word) }).value;
    // x86-64 epilogue: restore rbp
    return ((union { unsigned int bits; float value; }){ .value = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x43800000) }).value * value) }).bits;
}

gcc -O0

7/8
f201_f32_single_bits pass 18 lines
// glaurung: f201_f32_single_bits @ 0x122d
int32_t f201_f32_single_bits(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    float value;
    unsigned int word;
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_8 = (long)(0x28);
    value = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 2))) + 1)))));
    word = ((union { unsigned int bits; float value; }){ .value = value }).bits;
    ret = (unsigned long)((unsigned int)(((unsigned int)(word) >> 16)));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_f32_slot_bits pass 23 lines
// glaurung: f201_f32_slot_bits @ 0x1119
int32_t f201_f32_slot_bits(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char local_10[8];
    unsigned char local_18[8];
    long local_8;
    long ret;
    long var28;
    long var37;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    *(float *)(&local_18[0]) = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1)))));
    *(float *)((&local_18[0] + 4)) = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0))))) + 3)))));
    *(long *)(&local_10[0]) = *(long *)(&local_18[0]);
    var28 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) >> 23)));
    var37 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_10[0] + 4)))) >> 20)));
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var37)) << 2))) + var37))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var28)) + (unsigned long)((unsigned int)(var28))))) + var28))))));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_f32_slot_values pass 21 lines
// glaurung: f201_f32_slot_values @ 0x1350
int32_t f201_f32_slot_values(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char local_10[8];
    long local_8;
    long ret;
    int var42;
    int var52;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_8 = (long)(0x28);
    *(float *)(&local_10[0]) = ((float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1))))) / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40000000) }).value);
    *(float *)((&local_10[0] + 4)) = ((float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0))))) + 3))))) / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40800000) }).value);
    var42 = (int)(*(float *)(&local_10[0]));
    var52 = (int)(*(float *)((&local_10[0] + 4)));
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var52)) << 2))) + var52))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var42)) + (unsigned long)((unsigned int)(var42))))) + var42))))));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_f64_copy_then_convert pass 20 lines
// glaurung: f201_f64_copy_then_convert @ 0x13e6
int32_t f201_f64_copy_then_convert(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    double value;
    double copy;
    long local_8;
    long ret;
    int var32;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    value = ((double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((unsigned long)((unsigned int)(arg0)))) + (unsigned long)((unsigned int)((unsigned long)((unsigned int)(arg0))))))) + (unsigned long)((unsigned int)(arg0))))) + 1))))) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4020000000000000) }).value);
    copy = value;
    var32 = (int)(copy);
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var32)) << 3))) - var32)));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_f64_slot_bits pass 26 lines
// glaurung: f201_f64_slot_bits @ 0x119d
int32_t f201_f64_slot_bits(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char local_20[16];
    unsigned char local_30[16];
    long local_8;
    long ret;
    long var26;
    long var29;
    long var36;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    *(double *)(&local_30[0]) = (double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + 1)))));
    *(double *)((&local_30[0] + 8)) = (double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0))))) + 3)))));
    var26 = *(long *)((&local_30[0] + 8));
    *(long *)(&local_20[0]) = *(long *)(&local_30[0]);
    *(long *)((&local_20[0] + 8)) = var26;
    var29 = (unsigned long)((unsigned int)(((unsigned long)(*(long *)(&local_20[0])) >> 52)));
    var36 = (unsigned long)((unsigned int)(((unsigned long)(*(long *)((&local_20[0] + 8))) >> 48)));
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var36)) << 2))) + var36))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var29)) + (unsigned long)((unsigned int)(var29))))) + var29))))));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_scalar_control pass 23 lines
// glaurung: f201_scalar_control @ 0x1457
int32_t f201_scalar_control(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned char local_10[8];
    unsigned char local_18[8];
    long local_8;
    long ret;
    long var12;
    long var17;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_8 = (long)(0x28);
    *(int *)(&local_18[0]) = ((unsigned long)((unsigned int)(arg0)) + 1);
    *(int *)((&local_18[0] + 4)) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0))))) + 3);
    *(long *)(&local_10[0]) = *(long *)(&local_18[0]);
    var12 = (unsigned long)((unsigned int)(*(int *)(&local_10[0])));
    var17 = (unsigned long)((unsigned int)(*(int *)((&local_10[0] + 4))));
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) << 2))) + var17))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var12)) + (unsigned long)((unsigned int)(var12))))) + var12))))));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_store_through_pointer pass 22 lines
// glaurung: f201_store_through_pointer @ 0x1283
int32_t f201_store_through_pointer(int32_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    float value;
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_8 = (long)(0x28);
    ret = 0;
    value = (float)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) + 7)))));
    if ((arg0 != 0)) {
        *(float *)((long)arg0) = value;
        ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((long)arg0))) >> 21)));
    } else {
        ret = 0xffffffff;
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
f201_word_to_value fail 18 lines
// glaurung: f201_word_to_value @ 0x12ee
int32_t f201_word_to_value(int32_t arg0) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    unsigned int word;
    float value;
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_8 = (long)(0x28);
    word = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 8))) & 0x7f00)) | 0x41000000);
    value = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(word) }).value;
    ret = ((union { unsigned int bits; float value; }){ .value = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x43800000) }).value * value) }).bits;
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}

← 213 fixtures