Fixture 191
indirect table args
C · 4 functions · 4 lanes · 15 of 16 function-lanes behave identically
One lane has a function that returns a different result after decompilation: gcc-O2 (3/4).
Arguments to a call through a function-pointer table.
An indirect call has no single callee to ask which registers it reads, so a dead-code pass with no may-use set for it deletes the argument setup — and the recovered call then passes whatever happens to be in those registers. That output still compiles and still looks plausible; see docs/design/table-dispatch-arguments-2026-08-12.md, where a first attempt at repairing it emitted the right ARITY with the wrong VALUES.
A call through a *proven* table is different: the table's entries are a complete, relocation-proven callee set, so the registers the call may read are the union over that set. This fixture exists to make both halves of that observable — the arity AND the values.
Every entry records the exact arguments it received in the caller's own scratch buffer. 95_function_pointer_table already covers the value the dispatch RETURNS; a witness catches an argument list that is wrong in a way the returned value happens to hide, which is exactly the failure mode above. The count is kept in the caller's buffer rather than a global so it survives the harness rebuilding one function against extern callees, in the same way 189_effectful_select counts its side effect.
t191_computed_args is the NEAR-MISS CONTROL. Its table call passes values this function computed, not the parameters it was handed, so a recovery that names architectural argument registers and lets naming render them as arg1, arg2 produces well-typed, plausible, WRONG output and is caught here.
t191_direct_control is the DEGENERACY CONTROL: the same protocol through a DIRECT call, which the ordinary direct-callee recovery already handles. It must keep passing, so a decompiler cannot satisfy this fixture by making every call conservative.
#include <stdint.h>
/* Arguments to a call through a function-pointer table.
*
* An indirect call has no single callee to ask which registers it reads, so a
* dead-code pass with no may-use set for it deletes the argument setup — and
* the recovered call then passes whatever happens to be in those registers.
* That output still compiles and still looks plausible; see
* `docs/design/table-dispatch-arguments-2026-08-12.md`, where a first attempt
* at repairing it emitted the right ARITY with the wrong VALUES.
*
* A call through a *proven* table is different: the table's entries are a
* complete, relocation-proven callee set, so the registers the call may read
* are the union over that set. This fixture exists to make both halves of that
* observable — the arity AND the values.
*
* Every entry records the exact arguments it received in the caller's own
* scratch buffer. `95_function_pointer_table` already covers the value the
* dispatch RETURNS; a witness catches an argument list that is wrong in a way
* the returned value happens to hide, which is exactly the failure mode above.
* The count is kept in the caller's buffer rather than a global so it survives
* the harness rebuilding one function against extern callees, in the same way
* `189_effectful_select` counts its side effect.
*
* `t191_computed_args` is the NEAR-MISS CONTROL. Its table call passes values
* this function computed, not the parameters it was handed, so a recovery that
* names architectural argument registers and lets naming render them as
* `arg1, arg2` produces well-typed, plausible, WRONG output and is caught here.
*
* `t191_direct_control` is the DEGENERACY CONTROL: the same protocol through a
* DIRECT call, which the ordinary direct-callee recovery already handles. It
* must keep passing, so a decompiler cannot satisfy this fixture by making
* every call conservative. */
#define T191_SLOT_A 0
#define T191_SLOT_B 1
#define T191_SLOT_CALLS 2
#define T191_SLOT_WITNESS 3
typedef int32_t (*T191Op)(int32_t *witness, int32_t a, int32_t b);
__attribute__((noinline)) static int32_t t191_add(int32_t *witness, int32_t a, int32_t b) {
witness[T191_SLOT_A] = a;
witness[T191_SLOT_B] = b;
witness[T191_SLOT_CALLS] += 1;
return (int32_t)((uint32_t)a + (uint32_t)b);
}
__attribute__((noinline)) static int32_t t191_sub(int32_t *witness, int32_t a, int32_t b) {
witness[T191_SLOT_A] = a;
witness[T191_SLOT_B] = b;
witness[T191_SLOT_CALLS] += 1;
return (int32_t)((uint32_t)a - (uint32_t)b);
}
__attribute__((noinline)) static int32_t t191_and(int32_t *witness, int32_t a, int32_t b) {
witness[T191_SLOT_A] = a;
witness[T191_SLOT_B] = b;
witness[T191_SLOT_CALLS] += 1;
return a & b;
}
__attribute__((noinline)) static int32_t t191_max(int32_t *witness, int32_t a, int32_t b) {
witness[T191_SLOT_A] = a;
witness[T191_SLOT_B] = b;
witness[T191_SLOT_CALLS] += 1;
return a > b ? a : b;
}
static T191Op const T191_OPS[4] = {t191_add, t191_sub, t191_and, t191_max};
/* The plain shape. At -O2 the compiler leaves the incoming registers alone
* where it can and shuffles the rest into place BEFORE the bounds check, so the
* setup is not adjacent to the call and not inside the guarded arm either. */
__attribute__((noinline)) int32_t t191_dispatch(int32_t *scratch, int32_t which,
int32_t a, int32_t b) {
int32_t produced;
if (scratch == 0) {
return -1;
}
scratch[T191_SLOT_A] = 0;
scratch[T191_SLOT_B] = 0;
scratch[T191_SLOT_CALLS] = 0;
if (which < 0 || which >= 4) {
return -1;
}
produced = T191_OPS[which](scratch, a, b);
scratch[T191_SLOT_WITNESS] = produced;
return produced;
}
/* NEAR-MISS CONTROL: the arguments are computed here, so passing this
* function's own parameter registers is a different answer with the same
* shape. */
__attribute__((noinline)) int32_t t191_computed_args(int32_t *scratch, int32_t which,
int32_t seed) {
int32_t produced;
int32_t left;
int32_t right;
if (scratch == 0) {
return -1;
}
scratch[T191_SLOT_A] = 0;
scratch[T191_SLOT_B] = 0;
scratch[T191_SLOT_CALLS] = 0;
if (which < 0 || which >= 4) {
return -1;
}
left = (int32_t)((uint32_t)seed * 3u + 1u);
right = seed ^ 0x5a;
produced = T191_OPS[which](scratch, left, right);
scratch[T191_SLOT_WITNESS] = produced;
return produced;
}
/* The dispatch loop: the accumulator is carried round the back edge and is the
* argument of the next call, so the reaching value at the call is not the
* function's entry value for that register. */
__attribute__((noinline)) int32_t t191_fold(int32_t *scratch, const int32_t *selectors,
int32_t count, int32_t seed) {
int32_t accumulator = seed;
int32_t index;
if (scratch == 0 || selectors == 0 || count < 0 || count > 16) {
return -1;
}
scratch[T191_SLOT_A] = 0;
scratch[T191_SLOT_B] = 0;
scratch[T191_SLOT_CALLS] = 0;
for (index = 0; index < count; ++index) {
int32_t which = selectors[index];
if (which < 0 || which >= 4) {
continue;
}
accumulator = T191_OPS[which](scratch, accumulator, index + 1);
}
scratch[T191_SLOT_WITNESS] = accumulator;
return accumulator;
}
/* DEGENERACY CONTROL: one entry, called directly. Nothing about the indirect
* may-use set may disturb the recovery that already works. */
__attribute__((noinline)) int32_t t191_direct_control(int32_t *scratch, int32_t a,
int32_t b) {
int32_t produced;
if (scratch == 0) {
return -1;
}
scratch[T191_SLOT_A] = 0;
scratch[T191_SLOT_B] = 0;
scratch[T191_SLOT_CALLS] = 0;
produced = t191_add(scratch, a, b);
scratch[T191_SLOT_WITNESS] = produced;
return produced;
} 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
3/4t191_computed_args pass 34 lines
// glaurung: t191_computed_args @ 0x11d0
int32_t t191_computed_args(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int produced;
int right;
long local_8;
int ret;
long var1;
long var2;
if ((arg0 == 0)) {
return (unsigned int)(-1);
}
local_8 = var1;
var2 = (long)arg0;
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
if (((unsigned long)(3) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
ret = ((int (*)(int *, long, long, long))(T191_OPS[(long)(arg1)]))((int *)(arg0), (unsigned long)((unsigned int)(((arg2 + (arg2 * 2)) + 1))), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) ^ 90))), 0x3e60);
*(int *)((var2 + 0xc)) = ret;
// x86-64 epilogue: tear down frame
return ret;
} t191_direct_control pass 14 lines
// glaurung: t191_direct_control @ 0x12c0
int32_t t191_direct_control(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int t191_add(int *, int, int);
int produced;
int ret;
if ((arg0 == 0)) {
return 0xffffffff;
}
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
ret = t191_add((int *)(arg0), arg1, arg2);
*(int *)(((long)arg0 + 0xc)) = ret;
return ret;
} t191_dispatch pass 35 lines
// glaurung: t191_dispatch @ 0x1180
int32_t t191_dispatch(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int produced;
long local_8;
int ret;
long var1;
long var2;
long var3;
if ((arg0 == 0)) {
return (unsigned int)(-1);
}
var1 = (long)(arg1);
local_8 = var2;
var3 = (long)arg0;
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
if (((unsigned long)(3) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
ret = ((int (*)(int *, long, long, long))(T191_OPS[var1]))((int *)(arg0), (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)), 0x3e60);
*(int *)((var3 + 0xc)) = ret;
// x86-64 epilogue: tear down frame
return ret;
} t191_fold fail 71 lines
// glaurung: t191_fold @ 0x1230
int32_t t191_fold(int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int accumulator;
int which;
int index;
long local_10;
long local_18;
long local_28;
long local_8;
long var1;
long var13;
long var14;
long var16;
long var18;
long var2;
long var23;
long var3;
long var4;
long var5;
if ((arg0 == 0)) {
return (unsigned int)(-1);
}
local_8 = var1;
local_10 = var2;
local_18 = var3;
var4 = (long)arg1;
local_28 = var5;
if ((arg1 == 0)) {
accumulator = 0xffffffff;
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
var13 = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
accumulator = 0xffffffff;
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
*(long *)(((long)arg0)) = 0;
var14 = (long)arg0;
accumulator = (unsigned long)((unsigned int)(arg3));
*(int *)(((long)arg0 + 0x8)) = 0;
if (((unsigned long)((unsigned int)(arg2)) != 0)) {
var16 = 0;
var18 = (unsigned long)((unsigned int)(accumulator));
do {
which = (unsigned long)((unsigned int)(*(int *)((var4))));
var16 = (unsigned long)((unsigned int)((var16 + 1)));
accumulator = var18;
if (((unsigned long)((unsigned long)((unsigned int)(which))) <= (unsigned long)(3))) {
var23 = ((long (*)(long))(T191_OPS[(long)(which)]))(var14);
accumulator = (unsigned long)((unsigned int)(var23));
}
var4 = (var4 + 4);
var18 = (unsigned long)((unsigned int)(accumulator));
} while (((unsigned int)(var13) != (unsigned int)(var16)));
}
*(int *)((var14 + 0xc)) = accumulator;
// x86-64 epilogue: tear down frame
return (unsigned int)(accumulator);
} clang -O0
4/4t191_computed_args pass 43 lines
// glaurung: t191_computed_args @ 0x11b0
int32_t t191_computed_args(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int left;
int right;
int produced;
int local_4;
long var12;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg0) = 0;
*(int *)(((long)arg0 + 0x4)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
if ((0 <= (long)(arg1))) {
if (((long)(arg1) < 4)) {
goto L_1219;
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1219: ;
left = ((arg2 * 3) + 1);
right = ((unsigned int)(arg2) ^ 90);
var12 = ((long (*)(int *, long, long))(T191_OPS[(long)(arg1)]))((int *)(arg0), (unsigned long)((unsigned int)(left)), (unsigned long)((unsigned int)(right)));
produced = var12;
*(int *)(((long)arg0 + 0xc)) = produced;
local_4 = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} t191_direct_control pass 18 lines
// glaurung: t191_direct_control @ 0x1370
int32_t t191_direct_control(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int t191_add(int *, int, int);
int produced;
int var3;
// x86-64 prologue: save rbp, frame 32 bytes
if ((arg0 != 0)) {
*(int *)((long)arg0) = 0;
*(int *)(((long)arg0 + 0x4)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
var3 = t191_add((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
produced = var3;
*(int *)(((long)arg0 + 0xc)) = produced;
return (unsigned int)(produced);
} else {
return (unsigned int)(-1);
}
} t191_dispatch pass 39 lines
// glaurung: t191_dispatch @ 0x1100
int32_t t191_dispatch(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int produced;
int local_4;
long var6;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg0) = 0;
*(int *)(((long)arg0 + 0x4)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
if ((0 <= (long)(arg1))) {
if (((long)(arg1) < 4)) {
goto L_116c;
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_116c: ;
var6 = ((long (*)(int *, long, long))(T191_OPS[(long)(arg1)]))((int *)(arg0), (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
produced = var6;
*(int *)(((long)arg0 + 0xc)) = produced;
local_4 = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} t191_fold pass 62 lines
// glaurung: t191_fold @ 0x1270
int32_t t191_fold(int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int accumulator;
int index;
int which;
int local_4;
long var13;
// x86-64 prologue: save rbp, frame 48 bytes
accumulator = arg3;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if ((arg1 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg2) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg0) = 0;
*(int *)(((long)arg0 + 0x4)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
index = 0;
while ((index < arg2)) {
which = arg1[(long)(index)];
if (((long)(which) < 0)) {
L_1317: ;
} else {
if (((long)(which) < 4)) {
var13 = ((long (*)(int *, long, long))(T191_OPS[(long)(which)]))((int *)(arg0), (unsigned long)((unsigned int)(accumulator)), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) + 1))));
accumulator = var13;
} else {
goto L_1317;
}
}
index = ((unsigned int)(index) + 1);
}
*(int *)(((long)arg0 + 0xc)) = accumulator;
local_4 = accumulator;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
4/4t191_computed_args pass 40 lines
// glaurung: t191_computed_args @ 0x1140
int32_t t191_computed_args(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int left;
int produced;
int right;
long local_8;
long ret;
long var0;
long var1;
long var10;
long var3;
local_8 = var0;
var1 = 0xffffffff;
ret = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
var3 = (long)arg0;
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
ret = var1;
if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(3))) {
var10 = ((long (*)(long, long, long))(T191_OPS[(unsigned long)((unsigned int)(arg1))]))(var3, (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg2 + (arg2 * 2)))) + 1))), (unsigned long)((unsigned int)((arg2 ^ 90))));
*(int *)((var3 + 0xc)) = var10;
ret = var10;
}
// x86-64 epilogue: tear down frame
return ret;
} t191_direct_control pass 17 lines
// glaurung: t191_direct_control @ 0x1220
int32_t t191_direct_control(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int t191_add(int *, int, int);
int produced;
int ret;
long var0;
if ((arg0 == 0)) {
return 0xffffffff;
}
var0 = (long)arg0;
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
ret = t191_add((int *)(arg0), arg1, arg2);
*(int *)((var0 + 0xc)) = ret;
// x86-64 epilogue: tear down frame
return ret;
} t191_dispatch pass 37 lines
// glaurung: t191_dispatch @ 0x1100
int32_t t191_dispatch(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int produced;
long local_8;
long var0;
long var1;
long var3;
long var6;
local_8 = var0;
var1 = 0xffffffff;
produced = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return produced;
}
var3 = (long)arg0;
*(long *)(((long)arg0)) = 0;
*(int *)(((long)arg0 + 0x8)) = 0;
produced = var1;
if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(3))) {
var6 = ((long (*)(long, long, long))(T191_OPS[(unsigned long)((unsigned int)(arg1))]))(var3, (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
produced = var6;
*(int *)((var3 + 0xc)) = var6;
}
// x86-64 epilogue: tear down frame
return produced;
} t191_fold pass 80 lines
// glaurung: t191_fold @ 0x1190
int32_t t191_fold(int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int index;
int accumulator;
long local_10;
long local_18;
long local_20;
long local_28;
long local_8;
long var0;
long var1;
long var13;
long var14;
long var15;
long var16;
long var2;
long var20;
long var22;
long var23;
long var3;
long var4;
long var5;
long var6;
long var7;
local_8 = var0;
local_10 = var1;
local_18 = var2;
local_20 = var3;
local_28 = var4;
var5 = (unsigned long)((unsigned int)(arg3));
var6 = 0xffffffff;
var7 = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var7);
}
var13 = (long)arg0;
var7 = var6;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var7);
}
var14 = (long)arg1;
var7 = var6;
if ((arg1 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var7);
}
*(long *)((var13)) = 0;
*(int *)((var13 + 0x8)) = 0;
var15 = var5;
if (((unsigned long)((unsigned int)(arg2)) != 0)) {
var16 = (unsigned long)((unsigned int)(arg2));
var20 = var5;
index = 0;
do {
var22 = (unsigned long)((unsigned int)(*(int *)((var14 + index * 4))));
index = (index + 1);
if (((unsigned long)(var22) < (unsigned long)(4))) {
var23 = ((long (*)(long, long, long))(T191_OPS[var22]))(var13, (unsigned long)((unsigned int)(var20)), (unsigned long)((unsigned int)(index)));
var20 = var23;
}
var15 = var20;
} while ((index != var16));
}
*(int *)((var13 + 0xc)) = var15;
var7 = (unsigned long)((unsigned int)(var15));
// x86-64 epilogue: tear down frame
return (unsigned int)(var15);
} gcc -O0
4/4t191_computed_args pass 39 lines
// glaurung: t191_computed_args @ 0x12bd
int32_t t191_computed_args(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int left;
int right;
int produced;
long var23;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
*(int *)((long)arg0) = 0;
*(int *)((arg0 + 1)) = 0;
*(int *)((arg0 + 2)) = 0;
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 3) | ((long)(arg1) < 3))) {
goto L_131d;
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_131d: ;
left = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) + (unsigned long)((unsigned int)(arg2))))) + (unsigned long)((unsigned int)(arg2)))) + 1);
right = ((unsigned int)(arg2) ^ 90);
var23 = ((long (*)(int *, long, long))(T191_OPS[(long)((int)((unsigned long)((unsigned int)(arg1))))]))((int *)(arg0), (unsigned long)((unsigned int)(left)), (unsigned long)((unsigned int)(right)));
produced = var23;
*(int *)((arg0 + 3)) = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(produced);
} t191_direct_control pass 18 lines
// glaurung: t191_direct_control @ 0x145d
int32_t t191_direct_control(int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int t191_add(int *, int, int);
int produced;
int var7;
// x86-64 prologue: save rbp, frame 32 bytes
if ((arg0 != 0)) {
*(int *)((long)arg0) = 0;
*(int *)((arg0 + 1)) = 0;
*(int *)((arg0 + 2)) = 0;
var7 = t191_add((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
produced = var7;
*(int *)((arg0 + 3)) = produced;
return (unsigned int)(produced);
} else {
return 0xffffffff;
}
} t191_dispatch pass 35 lines
// glaurung: t191_dispatch @ 0x121e
int32_t t191_dispatch(int32_t * arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int produced;
long var12;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
*(int *)((long)arg0) = 0;
*(int *)((arg0 + 1)) = 0;
*(int *)((arg0 + 2)) = 0;
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 3) | ((long)(arg1) < 3))) {
goto L_127e;
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_127e: ;
var12 = ((long (*)(int *, long, long))(T191_OPS[(long)((int)((unsigned long)((unsigned int)(arg1))))]))((int *)(arg0), (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
produced = var12;
*(int *)((arg0 + 3)) = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(produced);
} t191_fold pass 49 lines
// glaurung: t191_fold @ 0x1374
int32_t t191_fold(int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern void t191_add(void);
extern void t191_and(void);
extern void t191_max(void);
extern void t191_sub(void);
static void (*T191_OPS[4])(void) = {
(void (*)(void))t191_add,
(void (*)(void))t191_sub,
(void (*)(void))t191_and,
(void (*)(void))t191_max,
};
int accumulator;
int index;
int which;
long var21;
// x86-64 prologue: save rbp, frame 48 bytes
accumulator = arg3;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((arg1 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((long)(arg2) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
*(int *)((long)arg0) = 0;
*(int *)((arg0 + 1)) = 0;
*(int *)((arg0 + 2)) = 0;
for (index = 0; (index < arg2); index++) {
which = arg1[(long)(index)];
if ((((long)(which) < 0) || ((((unsigned long)((unsigned int)(which)) == 3) | ((long)(which) < 3)) == 0))) {
} else {
var21 = ((long (*)(int *, long, long))(T191_OPS[(long)((int)((unsigned long)((unsigned int)(which))))]))((int *)(arg0), (unsigned long)((unsigned int)(accumulator)), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) + 1))));
accumulator = var21;
}
}
*(int *)((arg0 + 3)) = accumulator;
// x86-64 epilogue: restore rbp
return (unsigned int)(accumulator);
}