Fixture 166

rust generics

Rust · 7 functions · 2 lanes · 5 of 14 function-lanes behave identically

2 of 2 lanes have a function that returns a different result after decompilation: rustc-O2 (1/7), rustc-O0 (4/7).

tests/decompiler_fixtures/src/166_rust_generics.rs source
// 166_rust_generics.rs
//
// Rust monomorphized generics. A single generic function body is instantiated at
// three concrete integer widths (i8 / i16 / i32); the compiler emits three
// separate machine-code bodies with different truncation and sign-extension
// behaviour, and there is nothing in the binary that says they came from one
// source function. Recovering them means recovering three unrelated-looking
// functions that happen to share a shape.
//
// The interesting recovery signals:
//   * `<i8 as Acc>::step` truncates to 8 bits after every operation; the i16 and
//     i32 instantiations do not. Same source, three different width lattices.
//   * generic `pick`/`fold` monomorphise into bodies whose only difference is the
//     width of a compare and a move.
//   * at -O the instantiations are frequently inlined into the extern "C"
//     wrapper, so the wrapper's body is the ONLY evidence the generic existed.
//
// Exposure: every driver is `#[no_mangle] pub extern "C" fn` over plain i32/u32
// scalars and caller-owned `*const i32` / `*mut i32` buffers. Counts and indices
// are masked to <= 16 inside the wrapper, pointers are null-checked, and all
// arithmetic is `wrapping_*`, so no input the harness can pass can panic or run
// out of bounds. (rustc turns on overflow checks whenever opt-level is 0, so
// plain `+` would panic in the unoptimized lane on hostile fuzz values; the
// wrapping forms keep both lanes semantically identical.)
//
// Deterministic: no addresses, no allocation-order dependence, no time, no
// randomness.

#![allow(clippy::needless_range_loop)]

/// The generic bound. Every operation is width-preserving and wrapping, so an
/// instantiation is total over its whole domain.
trait Acc: Copy {
    /// Narrow an i32 into this accumulator's width.
    fn seed(v: i32) -> Self;
    /// One fold step; wraps at this type's width.
    fn step(self, k: i32) -> Self;
    /// Widen back to i32 (sign-extending).
    fn out(self) -> i32;
    /// Total order pick, at this type's width.
    fn pick_max(self, other: Self) -> Self;
}

impl Acc for i8 {
    fn seed(v: i32) -> Self {
        v as i8
    }
    fn step(self, k: i32) -> Self {
        // truncating multiply-accumulate: the i8 instantiation loses the high
        // bits that the i16/i32 ones keep.
        self.wrapping_mul(3).wrapping_add(k as i8)
    }
    fn out(self) -> i32 {
        self as i32
    }
    fn pick_max(self, other: Self) -> Self {
        if self >= other { self } else { other }
    }
}

impl Acc for i16 {
    fn seed(v: i32) -> Self {
        v as i16
    }
    fn step(self, k: i32) -> Self {
        self.wrapping_mul(3).wrapping_add(k as i16)
    }
    fn out(self) -> i32 {
        self as i32
    }
    fn pick_max(self, other: Self) -> Self {
        if self >= other { self } else { other }
    }
}

impl Acc for i32 {
    fn seed(v: i32) -> Self {
        v
    }
    fn step(self, k: i32) -> Self {
        self.wrapping_mul(3).wrapping_add(k)
    }
    fn out(self) -> i32 {
        self
    }
    fn pick_max(self, other: Self) -> Self {
        if self >= other { self } else { other }
    }
}

/// The one generic body. `#[inline(never)]` keeps a distinct symbol per
/// instantiation in the unoptimized lane; the optimized lane is free to inline
/// it anyway, which is exactly the contrast we want across lanes.
#[inline(never)]
fn fold_generic<T: Acc>(v: i32, n: u32) -> i32 {
    let mut acc = T::seed(v);
    let mut i: u32 = 0;
    while i < n {
        acc = acc.step(i as i32);
        i = i.wrapping_add(1);
    }
    acc.out()
}

/// A second generic body, over the same bound but a different shape (reduction
/// with a comparison instead of a chain of arithmetic).
#[inline(never)]
fn max_generic<T: Acc>(buf: &[i32]) -> i32 {
    let mut best = T::seed(if buf.is_empty() { 0 } else { buf[0] });
    for &x in buf {
        best = best.pick_max(T::seed(x));
    }
    best.out()
}

/// `n` is masked to 0..=15, so the loop is bounded for every possible input.
#[no_mangle]
pub extern "C" fn rust_generic_i8(v: i32, n: u32) -> i32 {
    fold_generic::<i8>(v, n & 15)
}

#[no_mangle]
pub extern "C" fn rust_generic_i16(v: i32, n: u32) -> i32 {
    fold_generic::<i16>(v, n & 15)
}

#[no_mangle]
pub extern "C" fn rust_generic_i32(v: i32, n: u32) -> i32 {
    fold_generic::<i32>(v, n & 15)
}

/// Runtime selection between the three instantiations. A decompiler that fuses
/// the three monomorphizations into one body gets this wrong for at least one
/// `sel`, because the widths differ.
#[no_mangle]
pub extern "C" fn rust_generic_dispatch(sel: u32, v: i32, n: u32) -> i32 {
    let n = n & 15;
    match sel % 3 {
        0 => fold_generic::<i8>(v, n),
        1 => fold_generic::<i16>(v, n),
        _ => fold_generic::<i32>(v, n),
    }
}

/// All three instantiations combined, so one call exercises every body.
#[no_mangle]
pub extern "C" fn rust_generic_mixed(v: i32, n: u32) -> i32 {
    let n = n & 15;
    let a = fold_generic::<i8>(v, n);
    let b = fold_generic::<i16>(v, n);
    let c = fold_generic::<i32>(v, n);
    a.wrapping_mul(1_000_003)
        .wrapping_add(b.wrapping_mul(7))
        .wrapping_add(c)
}

/// Generic reduction over a caller-owned buffer.
///
/// `p` is null-checked; `n` is clamped to at most 16 elements, which is the
/// harness's buffer allocation. `sel` picks the instantiation.
#[no_mangle]
pub extern "C" fn rust_generic_max(p: *const i32, n: u32, sel: u32) -> i32 {
    if p.is_null() {
        return -1;
    }
    let len = if n > 16 { 16 } else { n } as usize;
    // SAFETY: the caller owns at least 16 i32s at `p` (harness contract) and
    // `len <= 16`.
    let buf: &[i32] = unsafe { core::slice::from_raw_parts(p, len) };
    match sel % 3 {
        0 => max_generic::<i8>(buf),
        1 => max_generic::<i16>(buf),
        _ => max_generic::<i32>(buf),
    }
}

/// Generic write-back: each instantiation stores its own narrowed fold into the
/// caller's buffer, so the per-width truncation is observable as a buffer diff
/// and not only as a return value.
#[no_mangle]
pub extern "C" fn rust_generic_fill(out: *mut i32, n: u32, v: i32) -> i32 {
    if out.is_null() {
        return -1;
    }
    let len = if n > 16 { 16 } else { n } as usize;
    // SAFETY: caller owns >= 16 i32s at `out`; `len <= 16`.
    let dst: &mut [i32] = unsafe { core::slice::from_raw_parts_mut(out, len) };
    let mut sum: i32 = 0;
    for (i, slot) in dst.iter_mut().enumerate() {
        let k = (i & 15) as u32;
        let w = match i % 3 {
            0 => fold_generic::<i8>(v, k),
            1 => fold_generic::<i16>(v, k),
            _ => fold_generic::<i32>(v, k),
        };
        *slot = w;
        sum = sum.wrapping_add(w);
    }
    sum
}

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.

rustc -O2

1/7
rust_generic_dispatch pass 25 lines
// glaurung: rust_generic_dispatch @ 0x15f0
unsigned long rust_generic_dispatch(unsigned long arg0, unsigned int arg1, unsigned int arg2) {
    extern unsigned long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(unsigned int, long);
    extern unsigned long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(unsigned int, long);
    extern unsigned long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(unsigned int, long);
    unsigned long ret;
    long var1;
    long var5;
    int var7;
    long var8;
    var1 = (unsigned long)((unsigned int)((arg2 & 15)));
    var5 = ((unsigned long)((0xaaaaaaab * (unsigned long)((unsigned int)(arg0)))) >> 33);
    var7 = (arg0 - (unsigned int)((var5 + (var5 * 2))));
    var8 = (unsigned long)((unsigned int)(var7));
    if (((unsigned long)((unsigned int)(var7)) == 0)) {
        ret = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(arg1, (unsigned long)((unsigned int)(var1)));
        return ret;
    }
    if (((unsigned long)((unsigned int)(var8)) != 1)) {
        ret = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(arg1, (unsigned long)((unsigned int)(var1)));
        return ret;
    }
    ret = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(arg1, (unsigned long)((unsigned int)(var1)));
    return ret;
}
rust_generic_fill fail 57 lines
// glaurung: rust_generic_fill @ 0x16c0
unsigned int rust_generic_fill(char * arg0, unsigned int arg1, int arg2) {
    extern int _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(unsigned int, unsigned int);
    extern int _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(unsigned char, unsigned int);
    extern unsigned int _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(unsigned int, unsigned int);
    long var1;
    long var10;
    long var15;
    long var16;
    long var21;
    long var28;
    int var29;
    long var3;
    long var30;
    unsigned int var31;
    int var32;
    int var33;
    long var7;
    long var8;
    // x86-64 prologue: save callee registers, frame 56 bytes
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var3 = (((unsigned long)(arg1) < (unsigned long)(16)) ? arg1 : 16);
    if (((unsigned long)((unsigned int)(var3)) == 0)) {
        return 0;
    }
    var7 = (long)arg0;
    var8 = (var3 << 2);
    var10 = 0;
    var15 = 0;
    var16 = 0;
    do {
        var21 = ((unsigned long)(((unsigned long)(((unsigned __int128)(unsigned long)(var15) * (unsigned __int128)(unsigned long)(-0x5555555555555555LL)) >> 64))) >> 1);
        var28 = (var15 - (var21 + (var21 * 2)));
        if ((var28 == 0)) {
            var29 = ((int (*)(void))_ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E)();
            var30 = (unsigned long)((unsigned int)(var29));
        } else {
            if ((var28 != 1)) {
                var31 = ((unsigned int (*)(void))_ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE)();
                var30 = (unsigned long)(var31);
            } else {
                var32 = ((int (*)(void))_ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E)();
                var30 = (unsigned long)((unsigned int)(var32));
            }
        }
        *(int *)((var7 + var10)) = var30;
        var33 = (var16 + var30);
        var10 = (var10 + 4);
        var15 = (var15 + 1);
        var16 = (unsigned long)((unsigned int)(var33));
        var1 = (unsigned long)((unsigned int)(var33));
    } while ((var8 != var10));
    // x86-64 epilogue: restore callee registers
    return (unsigned int)(var1);
}
rust_generic_i16 fail 7 lines
// glaurung: rust_generic_i16 @ 0x15d0
long rust_generic_i16(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(void);
    long ret;
    ret = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E();
    return ret;
}
rust_generic_i32 fail 7 lines
// glaurung: rust_generic_i32 @ 0x15e0
long rust_generic_i32(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(void);
    long ret;
    ret = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE();
    return ret;
}
rust_generic_i8 fail 7 lines
// glaurung: rust_generic_i8 @ 0x15c0
long rust_generic_i8(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(void);
    long ret;
    ret = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E();
    return ret;
}
rust_generic_max fail 30 lines
// glaurung: rust_generic_max @ 0x1680
int rust_generic_max(char * arg0, int arg1, unsigned long arg2, long arg3, long arg4, long arg5) {
    extern int _ZN18_166_rust_generics11max_generic17h043ad3a9c196bfbbE(char *, int, unsigned long, long, long, long);
    extern int _ZN18_166_rust_generics11max_generic17h2042ccb8ba828c8eE(char *, int, unsigned long, long, long, long);
    extern int _ZN18_166_rust_generics11max_generic17hf0a9441020970678E(char *, int);
    int ret;
    long t35;
    long var0;
    long var5;
    int var7;
    long var8;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    t35 = (unsigned long)((unsigned int)(arg1));
    var5 = ((unsigned long)((0xaaaaaaab * (unsigned long)((unsigned int)(arg2)))) >> 33);
    var7 = (arg2 - (unsigned int)((var5 + (var5 * 2))));
    var8 = (unsigned long)((unsigned int)(var7));
    if (((unsigned long)((unsigned int)(var7)) == 0)) {
        ret = _ZN18_166_rust_generics11max_generic17h2042ccb8ba828c8eE(arg0, arg1, arg2, arg3, arg4, arg5);
        return ret;
    }
    if (((unsigned long)((unsigned int)(var8)) == 1)) {
        ret = _ZN18_166_rust_generics11max_generic17h043ad3a9c196bfbbE(arg0, arg1, arg2, arg3, arg4, arg5);
        return ret;
    }
    ret = _ZN18_166_rust_generics11max_generic17hf0a9441020970678E(arg0, (((unsigned long)(t35) < (unsigned long)(16)) ? var0 : 16));
    return ret;
}
rust_generic_mixed fail 23 lines
// glaurung: rust_generic_mixed @ 0x1630
unsigned int rust_generic_mixed(unsigned char arg0, unsigned int arg1) {
    extern int _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(unsigned int, unsigned int);
    extern int _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(unsigned char, unsigned int);
    extern unsigned int _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(unsigned int, unsigned int);
    long var1;
    unsigned int var10;
    long var3;
    int var4;
    long var6;
    int var7;
    long var9;
    // x86-64 prologue: save callee registers, frame 40 bytes
    var1 = (unsigned long)((unsigned int)((unsigned int)(arg0)));
    var3 = (unsigned long)((unsigned int)((arg1 & 15)));
    var4 = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(arg0, (unsigned long)((unsigned int)(var3)));
    var6 = (unsigned long)((unsigned int)(var4));
    var7 = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E((unsigned long)((unsigned int)(var1)), (unsigned long)((unsigned int)(var3)));
    var9 = (unsigned long)((unsigned int)(var7));
    var10 = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE((unsigned long)((unsigned int)(var1)), (unsigned long)((unsigned int)(var3)));
    // x86-64 epilogue: restore callee registers
    return (unsigned int)(((unsigned long)((unsigned int)((var10 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var9 * 8))) - var9)))))) + (var6 * 0xf4243)));
}

rustc -O0

4/7
rust_generic_dispatch pass 33 lines
// glaurung: rust_generic_dispatch @ 0x7c40
unsigned int rust_generic_dispatch(unsigned long arg0, unsigned int arg1, unsigned int arg2) {
    extern long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(int, unsigned int);
    int local_18;
    int local_1c;
    int local_4;
    long var1;
    long var11;
    long var16;
    long var18;
    long var7;
    int var9;
    var1 = (unsigned long)((unsigned int)((arg2 & 15)));
    local_1c = var1;
    local_4 = var1;
    var7 = (unsigned long)((unsigned int)(((unsigned long)(((unsigned long)((unsigned int)(arg0)) * 0xaaaaaaab)) >> 33)));
    var9 = (arg0 - (unsigned int)((var7 + (var7 * 2))));
    local_18 = var9;
    if (((unsigned long)((unsigned int)(var9)) == 0)) {
        var11 = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(arg1, (unsigned long)((unsigned int)(local_1c)));
        return (unsigned int)(var11);
    } else {
        if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_18)) - 1))) == 0)) {
            var16 = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(arg1, (unsigned long)((unsigned int)(local_1c)));
            return (unsigned int)(var16);
        } else {
            var18 = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(arg1, (unsigned long)((unsigned int)(local_1c)));
            return (unsigned int)(var18);
        }
    }
}
rust_generic_fill fail 99 lines
// glaurung: rust_generic_fill @ 0x7e60
__attribute__((no_stack_protector)) unsigned int rust_generic_fill(char * arg0, unsigned int arg1, int * arg2) {
    extern long _ZN110__LT_core__iter__adapters__enumerate__Enumerate_LT_I_GT__u20_as_u20_core__iter__traits__iterator__Iterator_GT_4next17h8483e9b67289d496E(char *);
    extern long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(int, unsigned int);
    extern int _ZN4core3ptr7mut_ptr31__LT_impl_u20__BP_mut_u20_T_GT_7is_null17h40f29bf35743d033E(char *);
    extern long * _ZN4core4iter6traits8iterator8Iterator9enumerate17hab1f645b7f7cb1c4E(long *);
    extern long _ZN4core5slice29__LT_impl_u20__u5b_T_u5d__GT_8iter_mut17h5e953d89ed368fc1E(long);
    extern long _ZN4core5slice3raw18from_raw_parts_mut17h68b114d220ea6601E(char *, long);
    extern long * _ZN63__LT_I_u20_as_u20_core__iter__traits__collect__IntoIterator_GT_9into_iter17h67beaf1f3a323f39E(long *);
    long local_18;
    long local_20;
    long local_30;
    long local_38;
    int local_4;
    int local_8;
    unsigned char local_90[72];
    unsigned char local_a8[24];
    int local_ac;
    int local_b0;
    int local_c;
    long local_d0;
    long local_d8;
    int local_dc;
    long local_e8;
    int var0;
    long var10;
    long * var13;
    long * var16;
    long var21;
    long var22;
    long var23;
    long var24;
    long var31;
    long var32;
    long var35;
    long var41;
    long var42;
    long var46;
    long var48;
    long var6;
    var0 = _ZN4core3ptr7mut_ptr31__LT_impl_u20__BP_mut_u20_T_GT_7is_null17h40f29bf35743d033E(arg0);
    if (((unsigned long)((unsigned char)((var0 & 1))) != 0)) {
        return (unsigned int)(-1);
    } else {
        local_b0 = (((unsigned long)(16) < (unsigned long)(arg1)) ? 16 : (unsigned long)(arg1));
        local_38 = (unsigned int)(local_b0);
        var6 = ((long (*)(char *))_ZN4core5slice3raw18from_raw_parts_mut17h68b114d220ea6601E)(arg0);
        local_30 = var6;
        local_ac = 0;
        var10 = ((long (*)(void))_ZN4core5slice29__LT_impl_u20__u5b_T_u5d__GT_8iter_mut17h5e953d89ed368fc1E)();
        var13 = _ZN4core4iter6traits8iterator8Iterator9enumerate17hab1f645b7f7cb1c4E((long *)(&local_90[0]));
        var16 = _ZN63__LT_I_u20_as_u20_core__iter__traits__collect__IntoIterator_GT_9into_iter17h67beaf1f3a323f39E((long *)(&local_a8[0]));
        *(long *)((&local_90[0] + 24)) = *(long *)(&local_a8[0]);
        *(long *)((&local_90[0] + 32)) = *(long *)((&local_a8[0] + 8));
        *(long *)((&local_90[0] + 40)) = *(long *)((&local_a8[0] + 16));
        var21 = var22;
        var23 = (long)arg2;
        while (1) {
            var24 = _ZN110__LT_core__iter__adapters__enumerate__Enumerate_LT_I_GT__u20_as_u20_core__iter__traits__iterator__Iterator_GT_4next17h8483e9b67289d496E((char *)((&local_90[0] + 24)));
            *(long *)((&local_90[0] + 56)) = var23;
            *(long *)((&local_90[0] + 48)) = var24;
            if ((((*(long *)((&local_90[0] + 56)) == 0) ? 0 : 1) == 0)) {
                break;
            }
            var31 = *(long *)((&local_90[0] + 48));
            local_d8 = var31;
            local_20 = var31;
            var32 = *(long *)((&local_90[0] + 56));
            local_e8 = var32;
            local_18 = var32;
            var35 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) & 15)));
            local_dc = var35;
            local_c = var35;
            var23 = ((unsigned long)(((unsigned long)(((unsigned __int128)(unsigned long)(var31) * (unsigned __int128)(unsigned long)(-0x5555555555555555LL)) >> 64))) >> 1);
            var41 = (local_d8 - (var23 + (var23 * 2)));
            local_d0 = var41;
            if ((var41 == 0)) {
                var42 = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E((unsigned long)((unsigned int)((long)arg2)), (unsigned long)((unsigned int)(local_dc)));
                *(int *)((&local_90[0] + 68)) = var42;
            } else {
                if ((local_d0 == 1)) {
                    var46 = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E((unsigned long)((unsigned int)((long)arg2)), (unsigned long)((unsigned int)(local_dc)));
                    *(int *)((&local_90[0] + 68)) = var46;
                } else {
                    var48 = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE((unsigned long)((unsigned int)((long)arg2)), (unsigned long)((unsigned int)(local_dc)));
                    *(int *)((&local_90[0] + 68)) = var48;
                }
            }
            *(int *)((local_e8)) = *(int *)((&local_90[0] + 68));
            var21 = (unsigned long)((unsigned int)(*(int *)((&local_90[0] + 68))));
            local_8 = local_ac;
            local_4 = var21;
            local_ac = ((unsigned int)(local_ac) + var21);
        }
        return (unsigned int)(local_ac);
    }
}
rust_generic_i16 pass 11 lines
// glaurung: rust_generic_i16 @ 0x7c00
long rust_generic_i16(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(long, unsigned int);
    int local_8;
    long ret;
    local_8 = ret;
    local_8 = arg0;
    ret = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(arg0, (unsigned long)((unsigned int)((arg1 & 15))));
    // x86-64 epilogue: tear down frame
    return ret;
}
rust_generic_i32 pass 11 lines
// glaurung: rust_generic_i32 @ 0x7c20
long rust_generic_i32(int arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(int, unsigned int);
    int local_8;
    long ret;
    local_8 = ret;
    local_8 = arg0;
    ret = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(arg0, (unsigned long)((unsigned int)((arg1 & 15))));
    // x86-64 epilogue: tear down frame
    return ret;
}
rust_generic_i8 pass 11 lines
// glaurung: rust_generic_i8 @ 0x7be0
long rust_generic_i8(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(long, unsigned int);
    int local_8;
    long ret;
    local_8 = ret;
    local_8 = arg0;
    ret = _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(arg0, (unsigned long)((unsigned int)((arg1 & 15))));
    // x86-64 epilogue: tear down frame
    return ret;
}
rust_generic_max fail 46 lines
// glaurung: rust_generic_max @ 0x7d60
__attribute__((no_stack_protector)) unsigned int rust_generic_max(char * arg0, unsigned int arg1, long arg2) {
    extern long _ZN18_166_rust_generics11max_generic17h043ad3a9c196bfbbE(int *);
    extern long _ZN18_166_rust_generics11max_generic17h2042ccb8ba828c8eE(int *);
    extern long _ZN18_166_rust_generics11max_generic17hf0a9441020970678E(int *);
    extern int _ZN4core3ptr9const_ptr33__LT_impl_u20__BP_const_u20_T_GT_7is_null17h6b4fb0ce318608e1E(char *);
    extern long _ZN4core5slice3raw14from_raw_parts17h0294aa453507db91E(char *, long);
    long local_10;
    long local_18;
    int local_2c;
    int local_44;
    unsigned char local_58[16];
    int var0;
    long var17;
    int var19;
    long var22;
    long var28;
    long var31;
    long var6;
    var0 = _ZN4core3ptr9const_ptr33__LT_impl_u20__BP_const_u20_T_GT_7is_null17h6b4fb0ce318608e1E(arg0);
    if (((unsigned long)((unsigned char)((var0 & 1))) != 0)) {
        return (unsigned int)(-1);
    } else {
        local_2c = (((unsigned long)(16) < (unsigned long)(arg1)) ? 16 : (unsigned long)(arg1));
        local_18 = (unsigned int)(local_2c);
        var6 = ((long (*)(char *))_ZN4core5slice3raw14from_raw_parts17h0294aa453507db91E)(arg0);
        *(long *)(&local_58[0]) = var6;
        *(long *)((&local_58[0] + 8)) = arg2;
        local_10 = var6;
        var17 = (unsigned long)((unsigned int)(((unsigned long)(((unsigned long)((unsigned int)(arg2)) * 0xaaaaaaab)) >> 33)));
        var19 = ((unsigned int)(arg2) - (unsigned int)((var17 + (var17 * 2))));
        local_44 = var19;
        if (((unsigned long)((unsigned int)(var19)) == 0)) {
            var22 = _ZN18_166_rust_generics11max_generic17h2042ccb8ba828c8eE((int *)(*(long *)(&local_58[0])));
            return (unsigned int)(var22);
        } else {
            if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_44)) - 1))) == 0)) {
                var28 = _ZN18_166_rust_generics11max_generic17h043ad3a9c196bfbbE((int *)(*(long *)(&local_58[0])));
                return (unsigned int)(var28);
            } else {
                var31 = _ZN18_166_rust_generics11max_generic17hf0a9441020970678E((int *)(*(long *)(&local_58[0])));
                return (unsigned int)(var31);
            }
        }
    }
}
rust_generic_mixed fail 43 lines
// glaurung: rust_generic_mixed @ 0x7cd0
__attribute__((no_stack_protector)) unsigned int rust_generic_mixed(long arg0, unsigned int arg1) {
    extern long _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E(long, unsigned int);
    extern long _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE(int, unsigned int);
    unsigned char local_48[72];
    long var1;
    long var10;
    long var11;
    int var12;
    int var13;
    long var2;
    long var4;
    long var6;
    long var8;
    *(int *)((&local_48[0] + 16)) = arg0;
    *(int *)((&local_48[0] + 20)) = arg1;
    var1 = (unsigned long)((unsigned int)((arg1 & 15)));
    *(int *)((&local_48[0] + 4)) = var1;
    *(int *)((&local_48[0] + 24)) = var1;
    var2 = ((long (*)(void))_ZN18_166_rust_generics12fold_generic17h75230eea90f483f4E)();
    *(int *)((&local_48[0] + 12)) = var2;
    *(int *)((&local_48[0] + 28)) = var2;
    var4 = _ZN18_166_rust_generics12fold_generic17h44a53adfaec6b0d4E((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(*(int *)((&local_48[0] + 4)))));
    *(int *)((&local_48[0] + 8)) = var4;
    *(int *)((&local_48[0] + 32)) = var4;
    var6 = _ZN18_166_rust_generics12fold_generic17h9974b21f4a73095cE((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(*(int *)((&local_48[0] + 4)))));
    var8 = (unsigned long)((unsigned int)(*(int *)((&local_48[0] + 8))));
    var10 = (unsigned long)((unsigned int)(*(int *)((&local_48[0] + 12))));
    *(int *)((&local_48[0] + 36)) = var6;
    *(int *)((&local_48[0] + 64)) = var10;
    *(int *)((&local_48[0] + 68)) = 0xf4243;
    var11 = (var10 * 0xf4243);
    *(int *)((&local_48[0] + 56)) = var8;
    *(int *)((&local_48[0] + 60)) = 7;
    var12 = (var8 * 7);
    *(int *)((&local_48[0] + 48)) = var11;
    *(int *)((&local_48[0] + 52)) = var12;
    var13 = (var11 + var12);
    *(int *)((&local_48[0] + 40)) = var13;
    *(int *)((&local_48[0] + 44)) = var6;
    return (unsigned int)(((unsigned long)((unsigned int)(var13)) + (unsigned long)((unsigned int)(var6))));
}

← 213 fixtures