Fixture 92
anonymous members
C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
C11 anonymous structs and unions: members of an unnamed member are addressed as if they belonged to the enclosing type, so the source names carry no offset information a decompiler can lean on.
#include <stdint.h>
/* C11 anonymous structs and unions: members of an unnamed member are addressed
* as if they belonged to the enclosing type, so the source names carry no
* offset information a decompiler can lean on. */
struct Message {
int32_t kind;
union {
struct {
int32_t x;
int32_t y;
};
struct {
int32_t code;
int32_t detail;
};
int32_t raw[2];
};
};
__attribute__((noinline)) int32_t
anonymous_select(int32_t kind, int32_t first, int32_t second, int32_t which) {
struct Message message;
message.kind = kind;
message.x = first;
message.y = second;
switch (which & 3) {
case 0:
return message.x + message.y;
case 1:
return message.code - message.detail;
case 2:
return message.raw[0];
default:
return message.raw[1];
}
}
__attribute__((noinline)) int32_t
anonymous_overlap_proof(int32_t value) {
struct Message message;
message.kind = 0;
message.code = value;
/* `x` and `code` name the same storage. */
return message.x == value;
} 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
2/2anonymous_overlap_proof pass 9 lines
// glaurung: anonymous_overlap_proof @ 0x1190
__attribute__((no_stack_protector)) int32_t anonymous_overlap_proof(int32_t arg0) {
unsigned char local_10[12];
// x86-64 prologue: save rbp
*(int *)(&local_10[0]) = 0;
*(int *)((&local_10[0] + 4)) = arg0;
// x86-64 epilogue: restore rbp
return ((unsigned int)(*(int *)((&local_10[0] + 4))) == (unsigned int)(arg0));
} anonymous_select pass 25 lines
// glaurung: anonymous_select @ 0x1100
__attribute__((no_stack_protector)) int32_t anonymous_select(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
unsigned char local_20[12];
int local_24;
int var4;
// x86-64 prologue: save rbp
*(int *)(&local_20[0]) = arg0;
*(int *)((&local_20[0] + 4)) = arg1;
*(int *)((&local_20[0] + 8)) = arg2;
var4 = ((unsigned int)(arg3) & 3);
local_24 = var4;
if (((unsigned long)((unsigned int)(var4)) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_20[0] + 4)))) + *(int *)((&local_20[0] + 8))));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_24)) - 1))) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_20[0] + 4)))) - *(int *)((&local_20[0] + 8))));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_24)) - 2))) == 0)) {
return (unsigned int)(*(int *)((&local_20[0] + 4)));
} else {
return (unsigned int)(*(int *)((&local_20[0] + 8)));
}
}
}
} clang -O2
2/2anonymous_overlap_proof pass 4 lines
// glaurung: anonymous_overlap_proof @ 0x1120
int32_t anonymous_overlap_proof(int32_t arg0) {
return 1;
} anonymous_select pass 20 lines
// glaurung: anonymous_select @ 0x1100
int32_t anonymous_select(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
long ret;
long var1;
long var2;
var1 = (unsigned long)((unsigned int)((arg3 & 3)));
var2 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)((unsigned int)(var1)) == 2)) {
return (unsigned int)(var2);
}
ret = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)((unsigned int)(var1)) == 1)) {
var2 = (unsigned long)((unsigned int)((arg1 - ret)));
return (unsigned int)(var2);
}
if (((unsigned long)((unsigned int)(var1)) != 0)) {
return ret;
}
return (unsigned int)((ret + arg1));
} gcc -O0
2/2anonymous_overlap_proof pass 17 lines
// glaurung: anonymous_overlap_proof @ 0x119f
int32_t anonymous_overlap_proof(int32_t arg0) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
unsigned char local_14[12];
long local_8;
long ret;
// x86-64 prologue: save rbp, frame 48 bytes
local_8 = (long)(0x28);
*(int *)(&local_14[0]) = 0;
*(int *)((&local_14[0] + 4)) = arg0;
ret = ((unsigned int)(arg0) == (unsigned int)(*(int *)((&local_14[0] + 4))));
if ((local_8 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} anonymous_select pass 37 lines
// glaurung: anonymous_select @ 0x1119
int32_t anonymous_select(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
unsigned char local_14[12];
long local_8;
long ret;
long var8;
// x86-64 prologue: save rbp, frame 48 bytes
local_8 = (long)(0x28);
*(int *)(&local_14[0]) = arg0;
*(int *)((&local_14[0] + 4)) = arg1;
*(int *)((&local_14[0] + 8)) = arg2;
var8 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) & 3)));
if (((unsigned long)((unsigned int)(var8)) == 2)) {
ret = (unsigned long)((unsigned int)(*(int *)((&local_14[0] + 4))));
} else {
if (((((unsigned long)((unsigned int)(var8)) == 2) | ((long)((int)(var8)) < 2)) == 0)) {
L_1186: ;
ret = (unsigned long)((unsigned int)(*(int *)((&local_14[0] + 8))));
} else {
if (((unsigned long)((unsigned int)(var8)) == 0)) {
ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_14[0] + 8)))) + (unsigned long)((unsigned int)(*(int *)((&local_14[0] + 4)))))));
} else {
if (((unsigned long)((unsigned int)(var8)) == 1)) {
ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_14[0] + 4)))) - (unsigned long)((unsigned int)(*(int *)((&local_14[0] + 8)))))));
} else {
goto L_1186;
}
}
}
}
if ((local_8 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} gcc -O2
2/2anonymous_overlap_proof pass 4 lines
// glaurung: anonymous_overlap_proof @ 0x1130
int32_t anonymous_overlap_proof(int32_t arg0) {
return 1;
} anonymous_select pass 12 lines
// glaurung: anonymous_select @ 0x1100
int32_t anonymous_select(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
long var1;
var1 = (unsigned long)((unsigned int)((arg3 & 3)));
if (((unsigned long)((unsigned int)(var1)) == 1)) {
return (unsigned int)((arg1 - arg2));
}
if (((unsigned long)((unsigned int)(var1)) == 2)) {
return (unsigned int)(arg1);
}
return (((unsigned long)((unsigned int)(var1)) == 0) ? (unsigned long)((unsigned int)((arg1 + arg2))) : (unsigned long)((unsigned int)(arg2)));
}