Fixture 90
bitfields
C · 3 functions · 4 lanes · 12 of 12 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Bitfields: a plain int bitfield's signedness is implementation-defined, an explicitly signed 3-bit field holds -4..3, and reading one is a shift/mask pair whose exact widths must survive.
#include <stdint.h>
/* Bitfields: a plain `int` bitfield's signedness is implementation-defined, an
* explicitly signed 3-bit field holds -4..3, and reading one is a shift/mask
* pair whose exact widths must survive. */
struct Flags {
unsigned int low : 3;
unsigned int middle : 5;
signed int high : 4;
unsigned int rest : 20;
};
__attribute__((noinline)) int32_t
bitfield_extract(uint32_t packed, int32_t which) {
struct Flags flags;
flags.low = packed & 0x7u;
flags.middle = (packed >> 3) & 0x1Fu;
flags.high = (int32_t)((packed >> 8) & 0xFu);
flags.rest = (packed >> 12) & 0xFFFFFu;
switch (which & 3) {
case 0:
return (int32_t)flags.low;
case 1:
return (int32_t)flags.middle;
case 2:
return (int32_t)flags.high; /* sign-extends from 4 bits */
default:
return (int32_t)flags.rest;
}
}
__attribute__((noinline)) int32_t
bitfield_signed_range(int32_t value) {
struct Flags flags;
flags.low = 0;
flags.middle = 0;
flags.rest = 0;
flags.high = value; /* truncates to 4 bits, then sign-extends on read */
return flags.high;
}
__attribute__((noinline)) int32_t
bitfield_struct_size(void) {
return (int32_t)sizeof(struct Flags);
} 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
3/3bitfield_extract pass 26 lines
// glaurung: bitfield_extract @ 0x1100
__attribute__((no_stack_protector)) int32_t bitfield_extract(uint32_t arg0, int32_t arg1) {
unsigned char local_10[4];
int local_14;
int var33;
// x86-64 prologue: save rbp
*(int *)(&local_10[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) & -8))) | (unsigned long)((unsigned int)((arg0 & 7))));
*(int *)(&local_10[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) & -249))) | (unsigned long)((unsigned int)((arg0 & 248))));
*(int *)(&local_10[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) & -3841))) | (unsigned long)((unsigned int)((arg0 & 3840))));
*(int *)(&local_10[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) & 4095))) | (unsigned long)((unsigned int)((arg0 & -4096))));
var33 = ((unsigned int)(arg1) & 3);
local_14 = var33;
if (((unsigned long)((unsigned int)(var33)) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) & 7));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_14)) - 1))) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) >> 3))) & 31));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_14)) - 2))) == 0)) {
return (unsigned int)(((int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) << 20)) >> 28));
} else {
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_10[0]))) >> 12));
}
}
}
} bitfield_signed_range pass 11 lines
// glaurung: bitfield_signed_range @ 0x11e0
__attribute__((no_stack_protector)) int32_t bitfield_signed_range(int32_t arg0) {
unsigned char local_8[4];
// x86-64 prologue: save rbp
*(int *)(&local_8[0]) = ((unsigned long)((unsigned int)(*(int *)(&local_8[0]))) & 0xfffffff8);
*(int *)(&local_8[0]) = ((unsigned long)((unsigned int)(*(int *)(&local_8[0]))) & 0xffffff07);
*(int *)(&local_8[0]) = ((unsigned long)((unsigned int)(*(int *)(&local_8[0]))) & 4095);
*(int *)(&local_8[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_8[0]))) & -3841))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 15))) << 8))));
// x86-64 epilogue: restore rbp
return (unsigned int)(((int)(((unsigned long)((unsigned int)(*(int *)(&local_8[0]))) << 20)) >> 28));
} bitfield_struct_size pass 6 lines
// glaurung: bitfield_struct_size @ 0x1230
int32_t bitfield_struct_size(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 4;
} clang -O2
3/3bitfield_extract pass 17 lines
// glaurung: bitfield_extract @ 0x1100
int32_t bitfield_extract(uint32_t arg0, int32_t arg1) {
long var0;
long var2;
var0 = (unsigned long)(arg0);
var2 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var2)) == 2)) {
return (unsigned int)(((int)((var0 << 20)) >> 28));
}
if (((unsigned long)((unsigned int)(var2)) == 1)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 3))) & 31));
}
if (((unsigned long)((unsigned int)(var2)) != 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(var0)) >> 12));
}
return (unsigned int)(((unsigned long)(arg0) & 7));
} bitfield_signed_range pass 4 lines
// glaurung: bitfield_signed_range @ 0x1130
int32_t bitfield_signed_range(int32_t arg0) {
return (unsigned int)(((int)(((unsigned long)((unsigned int)(arg0)) << 28)) >> 28));
} bitfield_struct_size pass 4 lines
// glaurung: bitfield_struct_size @ 0x1140
int32_t bitfield_struct_size(void) {
return 4;
} gcc -O0
3/3bitfield_extract pass 34 lines
// glaurung: bitfield_extract @ 0x10f9
__attribute__((no_stack_protector)) int32_t bitfield_extract(uint32_t arg0, int32_t arg1) {
unsigned char local_4[4];
long var55;
long var62;
int var64;
// x86-64 prologue: save rbp
*(signed char *)(&local_4[0]) = ((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & -8))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 & 7))) & 7))));
*(signed char *)(&local_4[0]) = ((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & 7))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 3))) & 31))) * 8))));
*(signed char *)((&local_4[0] + 1)) = ((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((&local_4[0] + 1)))) & -16))) | (unsigned long)((unsigned int)((((signed char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 8))) << 4))) & 255)) >> 4) & 15))));
*(int *)(&local_4[0]) = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_4[0]))) & 4095))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 12))) & 0xfffff))) << 12))));
var55 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 3)));
if (((unsigned long)((unsigned int)(var55)) == 2)) {
return (int)((signed char)((((signed char)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((&local_4[0] + 1)))) << 4))) & 255)) >> 4) & 255)));
} else {
if (((((unsigned long)((unsigned int)(var55)) == 2) | ((long)((int)(var55)) < 2)) == 0)) {
var62 = (unsigned long)((unsigned int)(*(int *)(&local_4[0])));
var64 = ((unsigned long)((unsigned int)(var62)) >> 12);
// x86-64 epilogue: restore rbp
return (unsigned int)(var64);
}
if (((unsigned long)((unsigned int)(var55)) == 0)) {
return (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & 7))) & 255)));
} else {
if (((unsigned long)((unsigned int)(var55)) == 1)) {
return (unsigned int)((unsigned char)((((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & 255))) >> 3) & 255)));
} else {
var62 = (unsigned long)((unsigned int)(*(int *)(&local_4[0])));
var64 = ((unsigned long)((unsigned int)(var62)) >> 12);
return (unsigned int)(var64);
}
}
}
} bitfield_signed_range pass 11 lines
// glaurung: bitfield_signed_range @ 0x11be
__attribute__((no_stack_protector)) int32_t bitfield_signed_range(int32_t arg0) {
unsigned char local_4[4];
// x86-64 prologue: save rbp
*(signed char *)(&local_4[0]) = ((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & 248);
*(signed char *)(&local_4[0]) = ((unsigned int)((unsigned char)(*(char *)(&local_4[0]))) & 7);
*(int *)(&local_4[0]) = ((unsigned long)((unsigned int)(*(int *)(&local_4[0]))) & 4095);
*(signed char *)((&local_4[0] + 1)) = ((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((&local_4[0] + 1)))) & -16))) | (unsigned long)((unsigned int)((((signed char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 4))) & 255)) >> 4) & 15))));
// x86-64 epilogue: restore rbp
return (int)((signed char)((((signed char)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((&local_4[0] + 1)))) << 4))) & 255)) >> 4) & 255)));
} bitfield_struct_size pass 6 lines
// glaurung: bitfield_struct_size @ 0x1211
int32_t bitfield_struct_size(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 4;
} gcc -O2
3/3bitfield_extract pass 12 lines
// glaurung: bitfield_extract @ 0x1100
int32_t bitfield_extract(uint32_t arg0, int32_t arg1) {
long var1;
var1 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var1)) == 1)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 3))) & 31));
}
if (((unsigned long)((unsigned int)(var1)) == 2)) {
return (int)((signed char)((((signed char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 8))) << 4))) & 255)) >> 4) & 255)));
}
return (((unsigned long)((unsigned int)(var1)) != 0) ? (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 12))) : (unsigned long)((unsigned int)(((unsigned long)(arg0) & 7))));
} bitfield_signed_range pass 4 lines
// glaurung: bitfield_signed_range @ 0x1140
int32_t bitfield_signed_range(int32_t arg0) {
return (int)((signed char)((((signed char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 4))) & 255)) >> 4) & 255)));
} bitfield_struct_size pass 4 lines
// glaurung: bitfield_struct_size @ 0x1150
int32_t bitfield_struct_size(void) {
return 4;
}