Fixture 84
compound literals
C · 3 functions · 4 lanes · 10 of 12 function-lanes behave identically
One lane has a function that returns a different result after decompilation: clang-O0 (1/3).
C99 compound literals: an unnamed object with automatic storage inside a block. Its address is valid for the enclosing block only, and the object is a fresh one on every evaluation.
#include <stdint.h>
/* C99 compound literals: an unnamed object with automatic storage inside a
* block. Its address is valid for the enclosing block only, and the object is
* a fresh one on every evaluation. */
struct Pair {
int32_t first;
int32_t second;
};
static int32_t pair_span(const struct Pair *pair) {
return pair->first - pair->second;
}
__attribute__((noinline)) int32_t
compound_literal_argument(int32_t left, int32_t right) {
/* The literal lives until the end of this block. */
return pair_span(&(struct Pair){left, right});
}
__attribute__((noinline)) int32_t
compound_literal_array(int32_t index) {
if (index < 0 || index > 5) {
return -1;
}
return (int32_t[]){2, 3, 5, 7, 11, 13}[index];
}
__attribute__((noinline)) int32_t
compound_literal_in_loop(int32_t count) {
int32_t total = 0;
int32_t step;
if (count < 0 || count > 16) {
return -1;
}
for (step = 0; step < count; ++step) {
/* A distinct object each iteration. */
struct Pair local = (struct Pair){step, count - step};
total += pair_span(&local);
}
return total;
} 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/3compound_literal_argument fail 11 lines
// glaurung: compound_literal_argument @ 0x1100
__attribute__((no_stack_protector)) int32_t compound_literal_argument(int32_t arg0, int32_t arg1) {
extern int pair_span(char *);
unsigned char local_10[4];
int ret;
// x86-64 prologue: save rbp, frame 16 bytes
*(int *)(&local_10[0]) = arg0;
ret = pair_span((char *)(&local_10[0]));
// x86-64 epilogue: restore rbp
return ret;
} compound_literal_array fail 27 lines
// glaurung: compound_literal_array @ 0x1150
static unsigned char glaurung_global_4020[16] __attribute__((aligned(16)));
static unsigned char glaurung_global_4028[16] __attribute__((aligned(16)));
static unsigned char glaurung_global_4030[16] __attribute__((aligned(16)));
__attribute__((no_stack_protector)) int32_t compound_literal_array(int32_t arg0) {
extern unsigned char glaurung_global_4020[16];
extern unsigned char glaurung_global_4028[16];
extern unsigned char glaurung_global_4030[16];
unsigned char local_20[32];
// x86-64 prologue: save rbp
if (((long)(arg0) < 0)) {
*(int *)((&local_20[0] + 28)) = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(*(int *)((&local_20[0] + 28)));
}
if (((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5)) == 0)) {
*(int *)((&local_20[0] + 28)) = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(*(int *)((&local_20[0] + 28)));
}
*(long *)(&local_20[0]) = *(long *)(&glaurung_global_4020[0]);
*(long *)((&local_20[0] + 8)) = *(long *)(&glaurung_global_4028[0]);
*(long *)((&local_20[0] + 16)) = *(long *)(&glaurung_global_4030[0]);
*(int *)((&local_20[0] + 28)) = *(int *)((&local_20[0] + ((long)(arg0) * 4)));
// x86-64 epilogue: restore rbp
return (unsigned int)(*(int *)((&local_20[0] + 28)));
} compound_literal_in_loop pass 30 lines
// glaurung: compound_literal_in_loop @ 0x11b0
__attribute__((no_stack_protector)) int32_t compound_literal_in_loop(int32_t arg0) {
extern int pair_span(char *);
int total;
int step;
unsigned char local_18[8];
int local_4;
int var5;
// x86-64 prologue: save rbp, frame 32 bytes
total = 0;
if (((long)(arg0) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg0)) == 16) | ((long)(arg0) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
for (step = 0; (step < arg0); step++) {
*(int *)(&local_18[0]) = step;
*(int *)((&local_18[0] + 4)) = ((unsigned long)((unsigned int)(arg0)) - step);
var5 = pair_span((char *)(&local_18[0]));
total = (var5 + total);
}
local_4 = total;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
3/3compound_literal_argument pass 4 lines
// glaurung: compound_literal_argument @ 0x1100
int32_t compound_literal_argument(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1));
} compound_literal_array pass 9 lines
// glaurung: compound_literal_array @ 0x1110
int32_t compound_literal_array(int32_t arg0) {
long ret;
ret = 0xffffffff;
if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(5))) {
ret = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(arg0)) == 0) ? 2 : (((unsigned long)((unsigned int)(arg0)) == 1) ? 3 : (((unsigned long)((unsigned int)(arg0)) == 2) ? 5 : (((unsigned long)((unsigned int)(arg0)) == 3) ? 7 : (((unsigned long)((unsigned int)(arg0)) == 4) ? 11 : (((unsigned long)((unsigned int)(arg0)) == 5) ? 13 : *(int *)((0x2000 + ((unsigned long)((unsigned int)(arg0)) * 4)))))))))));
}
return ret;
} compound_literal_in_loop pass 16 lines
// glaurung: compound_literal_in_loop @ 0x1130
int32_t compound_literal_in_loop(int32_t arg0) {
int step;
int total;
long ret;
long var1;
ret = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
return ret;
}
if (((unsigned long)((unsigned int)(arg0)) == 0)) {
return 0;
}
var1 = (unsigned long)((unsigned int)((arg0 - 1)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 - 2))) * var1))) & -2))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((2 - arg0))) * var1)))))) - arg0));
} gcc -O0
3/3compound_literal_argument pass 19 lines
// glaurung: compound_literal_argument @ 0x1138
int32_t compound_literal_argument(int32_t arg0, int32_t arg1) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
extern int pair_span(char *);
unsigned char local_10[16];
long ret;
int var6;
// x86-64 prologue: save rbp, frame 32 bytes
*(long *)((&local_10[0] + 8)) = (long)((long)(0x28));
*(int *)(&local_10[0]) = arg0;
*(int *)((&local_10[0] + 4)) = arg1;
var6 = pair_span((char *)(&local_10[0]));
ret = (unsigned long)((unsigned int)(var6));
if ((*(long *)((&local_10[0] + 8)) != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} compound_literal_array pass 24 lines
// glaurung: compound_literal_array @ 0x1187
int32_t compound_literal_array(int32_t arg0) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
unsigned char local_20[32];
long ret;
// x86-64 prologue: save rbp, frame 48 bytes
*(long *)((&local_20[0] + 24)) = (long)((long)(0x28));
if ((((long)(arg0) < 0) || (((unsigned long)((unsigned int)(arg0)) != 5) && (5 <= (long)(arg0))))) {
ret = 0xffffffff;
} else {
*(int *)(&local_20[0]) = 2;
*(int *)((&local_20[0] + 4)) = 3;
*(int *)((&local_20[0] + 8)) = 5;
*(int *)((&local_20[0] + 12)) = 7;
*(int *)((&local_20[0] + 16)) = 11;
*(int *)((&local_20[0] + 20)) = 13;
ret = (unsigned long)((unsigned int)(*(int *)((&local_20[0] + ((long)(arg0) * 4)))));
}
if ((*(long *)((&local_20[0] + 24)) != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} compound_literal_in_loop pass 30 lines
// glaurung: compound_literal_in_loop @ 0x1201
int32_t compound_literal_in_loop(int32_t arg0) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
extern int pair_span(char *);
int total;
int step;
unsigned char local_10[8];
long local_8;
long ret;
int var9;
// x86-64 prologue: save rbp, frame 48 bytes
local_8 = (long)(0x28);
total = 0;
if ((((long)(arg0) < 0) || (((unsigned long)((unsigned int)(arg0)) != 16) && (16 <= (long)(arg0))))) {
ret = 0xffffffff;
} else {
for (step = 0; (step < arg0); step++) {
*(int *)(&local_10[0]) = step;
*(int *)((&local_10[0] + 4)) = ((unsigned long)((unsigned int)(arg0)) - step);
var9 = pair_span((char *)(&local_10[0]));
total = (total + var9);
}
ret = (unsigned long)((unsigned int)(total));
}
if ((local_8 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} gcc -O2
3/3compound_literal_argument pass 4 lines
// glaurung: compound_literal_argument @ 0x1120
int32_t compound_literal_argument(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1));
} compound_literal_array pass 19 lines
// glaurung: compound_literal_array @ 0x1130
int32_t compound_literal_array(int32_t arg0) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
unsigned char local_28[40];
long ret;
*(long *)((&local_28[0] + 24)) = (long)((long)(0x28));
if (((unsigned long)(5) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
ret = 0xffffffff;
} else {
*(long *)(&local_28[0]) = 0x300000002;
*(long *)((&local_28[0] + 8)) = 0x700000005;
*(long *)((&local_28[0] + 16)) = 0xd0000000b;
ret = (unsigned long)((unsigned int)(*(int *)((&local_28[0] + ((long)(arg0) * 4)))));
}
if ((*(long *)((&local_28[0] + 24)) != 0x28)) {
__stack_chk_fail();
}
return ret;
} compound_literal_in_loop pass 31 lines
// glaurung: compound_literal_in_loop @ 0x11b0
int32_t compound_literal_in_loop(int32_t arg0) {
int total;
int step;
long var3;
long var4;
int var6;
long var7;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
goto L_11e7;
}
if (((unsigned long)((unsigned int)(arg0)) == 0)) {
goto L_11e0;
}
var3 = (-(unsigned long)((unsigned int)(arg0)));
var4 = 0;
do {
total = (var4 + var3);
var4 = (unsigned long)((unsigned int)(total));
var6 = (var3 + 2);
var3 = (unsigned long)((unsigned int)(var6));
var7 = (unsigned long)((unsigned int)(total));
} while (((unsigned int)(arg0) != (unsigned int)(var6)));
L_11d2: ;
return (unsigned int)(var7);
L_11e0: ;
return 0;
L_11e7: ;
var7 = 0xffffffff;
goto L_11d2;
}