Fixture 105
goto ladder
C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
The kernel-style cleanup ladder: forward gotos into a reversed unwind chain where later labels fall through earlier ones. Structuring must recover the partial-cleanup order, not just the fact that a jump exists.
#include <stdint.h>
/* The kernel-style cleanup ladder: forward gotos into a reversed unwind chain
* where later labels fall through earlier ones. Structuring must recover the
* partial-cleanup order, not just the fact that a jump exists. */
__attribute__((noinline)) int32_t
acquire_and_release(int32_t stages, int32_t *log, int32_t capacity) {
int32_t released = 0;
int32_t status = 0;
if (log == 0 || capacity < 4 || stages < 0 || stages > 4) {
return -1;
}
log[0] = 0;
log[1] = 0;
log[2] = 0;
log[3] = 0;
if (stages < 1) {
status = -2;
goto done;
}
log[0] = 1;
if (stages < 2) {
status = -3;
goto release_first;
}
log[1] = 1;
if (stages < 3) {
status = -4;
goto release_second;
}
log[2] = 1;
if (stages < 4) {
status = -5;
goto release_third;
}
log[3] = 1;
status = stages;
released += 1;
release_third:
released += 1;
release_second:
released += 1;
release_first:
released += 1;
done:
return status * 10 + released;
} Recovered C
Generated by glaurung decompile --style decbench at b47f6b43.
baseline.json records the result after recompiling the C and calling it beside the
original with seeded inputs.
clang -O0
1/1acquire_and_release pass 61 lines
// glaurung: acquire_and_release @ 0x1100
int32_t acquire_and_release(int32_t arg0, int32_t * arg1, int32_t arg2) {
int released;
int status;
int local_4;
// x86-64 prologue: save rbp
released = 0;
status = 0;
if ((arg1 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg2) < 4)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg0) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg0)) == 4) | ((long)(arg0) < 4)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg1) = 0;
*(int *)(((long)arg1 + 0x4)) = 0;
*(int *)(((long)arg1 + 0x8)) = 0;
*(int *)(((long)arg1 + 0xc)) = 0;
if ((1 <= (long)(arg0))) {
*(int *)((long)arg1) = 1;
if ((2 <= (long)(arg0))) {
*(int *)(((long)arg1 + 0x4)) = 1;
if ((3 <= (long)(arg0))) {
*(int *)(((long)arg1 + 0x8)) = 1;
if ((4 <= (long)(arg0))) {
*(int *)(((long)arg1 + 0xc)) = 1;
status = arg0;
released = ((unsigned int)(released) + 1);
} else {
status = -5;
}
released = ((unsigned int)(released) + 1);
} else {
status = -4;
}
released = ((unsigned int)(released) + 1);
} else {
status = -3;
}
released = ((unsigned int)(released) + 1);
} else {
status = -2;
}
local_4 = ((status * 10) + released);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
1/1acquire_and_release pass 55 lines
// glaurung: acquire_and_release @ 0x1100
int32_t acquire_and_release(int32_t arg0, int32_t * arg1, int32_t arg2) {
int released;
int status;
long ret;
int var8;
long var9;
long zf_6;
ret = 0xffffffff;
if (((unsigned long)(4) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
return ret;
}
ret = 0xffffffff;
if ((arg1 == 0)) {
return ret;
}
ret = 0xffffffff;
if (((long)(arg2) < 4)) {
return ret;
}
*(int *)(((long)arg1)) = 0;
*(int *)(((long)arg1 + 0x4)) = 0;
*(int *)(((long)arg1 + 0x8)) = 0;
*(int *)(((long)arg1 + 0xc)) = 0;
if (((unsigned long)((unsigned int)(arg0)) == 0)) {
var8 = 0xffffffec;
var9 = 0;
} else {
*(int *)(((long)arg1)) = 1;
if (((unsigned long)((unsigned int)(arg0)) != 1)) {
*(int *)(((long)arg1 + 0x4)) = 1;
zf_6 = ((unsigned long)((unsigned int)(arg0)) == 3);
if (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
*(int *)(((long)arg1 + 0x8)) = 1;
if ((zf_6 == 0)) {
*(int *)(((long)arg1 + 0xc)) = 1;
var8 = 40;
var9 = 4;
} else {
var8 = 0xffffffce;
var9 = 3;
}
} else {
var8 = 0xffffffd8;
var9 = 2;
}
} else {
var8 = 0xffffffe2;
var9 = 1;
}
}
released = (var9 + var8);
ret = (unsigned long)((unsigned int)(released));
return (unsigned int)(released);
} gcc -O0
1/1acquire_and_release pass 57 lines
// glaurung: acquire_and_release @ 0x10f9
int32_t acquire_and_release(int32_t arg0, int32_t * arg1, int32_t arg2) {
int released;
int status;
int var19;
// x86-64 prologue: save rbp
released = 0;
status = 0;
if ((arg1 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((((unsigned long)((unsigned int)(arg2)) == 3) | ((long)(arg2) < 3))) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg0)) == 4) | ((long)(arg0) < 4)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
*(int *)((long)arg1) = 0;
*(int *)((arg1 + 1)) = 0;
*(int *)((arg1 + 2)) = 0;
*(int *)((arg1 + 3)) = 0;
if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0)) {
*(int *)((long)arg1) = 1;
if (((((unsigned long)((unsigned int)(arg0)) == 1) | ((long)(arg0) < 1)) == 0)) {
*(int *)((arg1 + 1)) = 1;
if (((((unsigned long)((unsigned int)(arg0)) == 2) | ((long)(arg0) < 2)) == 0)) {
*(int *)((arg1 + 2)) = 1;
if (((((unsigned long)((unsigned int)(arg0)) == 3) | ((long)(arg0) < 3)) == 0)) {
*(int *)((arg1 + 3)) = 1;
status = arg0;
released = (released + 1);
} else {
status = -5;
}
released = (released + 1);
} else {
status = -4;
}
released = (released + 1);
} else {
status = -3;
}
released = (released + 1);
} else {
status = -2;
}
var19 = ((unsigned int)(((unsigned long)((unsigned int)(status)) << 2)) + (unsigned int)(status));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(released)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var19)) + (unsigned long)((unsigned int)(var19)))))));
} gcc -O2
1/1acquire_and_release pass 34 lines
// glaurung: acquire_and_release @ 0x1100
int32_t acquire_and_release(int32_t arg0, int32_t * arg1, int32_t arg2) {
int released;
int status;
long ret;
if ((arg1 == 0)) {
return 0xffffffff;
}
if ((((unsigned long)((unsigned int)(arg2)) == 3) | ((long)(arg2) < 3))) {
return 0xffffffff;
}
if (((unsigned long)(4) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
return 0xffffffff;
}
*(long *)(((long)arg1)) = 0;
ret = 0xffffffec;
*(long *)(((long)arg1 + 0x8)) = 0;
if (((unsigned long)((unsigned int)(arg0)) != 0)) {
*(int *)(((long)arg1)) = 1;
ret = 0xffffffe3;
if (((unsigned long)((unsigned int)(arg0)) == 1)) {
return ret;
}
*(int *)(((long)arg1 + 0x4)) = 1;
ret = 0xffffffda;
if (((unsigned long)((unsigned int)(arg0)) != 2)) {
*(int *)(((long)arg1 + 0x8)) = 1;
ret = (((unsigned long)((unsigned int)(arg0)) == 3) ? 0xffffffd1 : 44);
*(int *)(((long)arg1 + 0xc)) = ((unsigned long)((unsigned int)(arg0)) != 3);
return ret;
}
}
return ret;
}