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).
// 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/7rust_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/7rust_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))));
}