main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rbp
__int64 v4; // rax

concurrent_init(argc, argv, envp);
v3 = (void *)strsplit_new_constprop_0();
while ( 1 )
{
v4 = strsplit_next(v3);
if ( !v4 )
break;
printf("%.*s\n", *(_QWORD *)(v4 + 8), *(const char **)v4);
}
strsplit_del(v3);
concurrent_fin();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rbp
__int64 v4; // rax

func17(argc, argv, envp);
v3 = (void *)func14();
while ( 1 )
{
v4 = func15(v3);
if ( !v4 )
break;
printf("%.*s\n", *(_QWORD *)(v4 + 8), *(const char **)v4);
}
func13(v3);
func18();
return 0;
}

original_code:
int main(void)
{
    uint8_t *stack;
    const int stack_size = 1024 * 4;
    int data[] = { 12, 13, 14, 15, 10, 9, 7, 1, 2, 11, 3, 4, 8, 6, 5, 0 };
    struct sort_ctx sort_arg;
    sort_arg.data = data;
    sort_arg.num_data = sizeof(data) / sizeof(data[0]);
    concurrent_init();
    g_context = malloc(concurrent_sizeof());
    stack = malloc(sizeof(*stack) * stack_size);
    concurrent_construct(g_context, stack, stack_size, coro, (void *)&sort_arg);
    while (!concurrent_is_done(g_context)) {
        size_t stack_size_used = concurrent_get_stack_used(g_context);
        printf("stack used:%3zdbytes(%2.0f%%); data={ ",
               stack_size_used, ((float)stack_size_used / stack_size) * 100.0f);
        print_datas(&sort_arg);
        printf("}\n");
        concurrent_resume(g_context);
    }
    concurrent_destruct(g_context);
    free(stack);
    free(g_context);
    concurrent_fin();
    return 0;
}


repo: sharow/libconcurrent

decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func16(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

original_code:
static void
concurrent_setup_execution_context(struct concurrent_ctx *ctx)
{
    ctx->stack_ptr = ctx->stack_base;
    concurrent_arch_setup_execution_context(ctx);
}

variable_types: struct concurrent_ctx { void (*proc)(struct concurrent_ctx *); void *user_ptr; void *stack_orig; unsigned long stack_size; unsigned long stack_base; unsigned long stack_ptr; enum concurrent_state { CONCURRENT_STATE_SETUP=0, CONCURRENT_STATE_EXECUTE=1, CONCURRENT_STATE_YIELD=2, CONCURRENT_STATE_DONE=3 } state; void *caller_return_addr; void *yield_value; void *resume_value; } *

return_type: void

user_defined_types: struct concurrent_ctx { void (*proc)(struct concurrent_ctx *); void *user_ptr; void *stack_orig; unsigned long stack_size; unsigned long stack_base; unsigned long stack_ptr; enum concurrent_state state; void *caller_return_addr; void *yield_value; void *resume_value; }


decompiled_code:
void concurrent_fin()
{
;
}

canonical_decompiled_code:
void func18()
{
;
}

original_code:
void
concurrent_fin(void)
{
}

canonical_original_code:
void concurrent_fin()
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
return 80LL;
}

canonical_decompiled_code:
__int64 func19()
{
return 80LL;
}

original_code:
size_t
concurrent_sizeof(void)
{
    return sizeof(struct concurrent_ctx);
}

canonical_original_code:
unsigned long concurrent_sizeof()
{
    return sizeof(struct concurrent_ctx);
}

return_type: unsigned long

user_defined_types: enum concurrent_state { CONCURRENT_STATE_SETUP=0, CONCURRENT_STATE_EXECUTE=1, CONCURRENT_STATE_YIELD=2, CONCURRENT_STATE_DONE=3 }


decompiled_code:
__int64 __fastcall concurrent_construct(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func20(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

original_code:
concurrent_status
concurrent_construct(struct concurrent_ctx *ctx,
                     void *stack_buffer,
                     size_t stack_size,
                     concurrent_proc proc,
                     void *user_ptr)
{
    const uintptr_t align = 16 - 1;
    uintptr_t aligned_stack_buffer;
    if (ctx && stack_buffer && proc) {
    } else {
        return CONCURRENT_E_INVALID_ARGUMENT;
    }
    if (stack_size < (1024)) {
        return CONCURRENT_E_STACKSIZE_TOO_SMALL;
    }
    aligned_stack_buffer = ((uintptr_t)stack_buffer + align) & ~align;
    (((uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer) ? (void) (0) : __assert_fail ("(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer", "src/concurrent.c", 94, __extension__ __PRETTY_FUNCTION__));
    ctx->proc = proc;
    ctx->user_ptr = user_ptr;
    ctx->stack_orig = stack_buffer;
    ctx->stack_size = (stack_size - (size_t)(aligned_stack_buffer - (uintptr_t)stack_buffer)) & ~(size_t)align;
    ctx->stack_base = aligned_stack_buffer + ctx->stack_size;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_SETUP;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
    return CONCURRENT_SUCCESS;
}

canonical_original_code:
enum concurrent_status concurrent_construct(struct concurrent_ctx *ctx, void *stack_buffer, unsigned long stack_size, void (*proc)(struct concurrent_ctx *), void *user_ptr)
{
    unsigned long align = 16 - 1;
    unsigned long aligned_stack_buffer;
    if (ctx && stack_buffer && proc) {
    } else {
        return CONCURRENT_E_INVALID_ARGUMENT;
    }
    if (stack_size < (1024)) {
        return CONCURRENT_E_STACKSIZE_TOO_SMALL;
    }
    aligned_stack_buffer = ((unsigned long)stack_buffer + align) & ~align;
    (((unsigned long)aligned_stack_buffer >= (unsigned long)stack_buffer) ? (void) (0) : __assert_fail ("(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer", "src/concurrent.c", 94, __extension__ __PRETTY_FUNCTION__));
    ctx->proc = proc;
    ctx->user_ptr = user_ptr;
    ctx->stack_orig = stack_buffer;
    ctx->stack_size = (stack_size - (unsigned long)(aligned_stack_buffer - (unsigned long)stack_buffer)) & ~(unsigned long)align;
    ctx->stack_base = aligned_stack_buffer + ctx->stack_size;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_SETUP;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
    return CONCURRENT_SUCCESS;
}

variable_types:
proc
void (*)(struct concurrent_ctx *)

variable_types:
align
unsigned long

return_type: enum concurrent_status { CONCURRENT_SUCCESS=0, CONCURRENT_E_INVALID_ARGUMENT=1, CONCURRENT_E_STACKSIZE_TOO_SMALL=2 }


original_code:
void
concurrent_destruct(struct concurrent_ctx *ctx)
{
    ctx->proc = ((void *)0);
    ctx->user_ptr = ((void *)0);
    ctx->stack_orig = ((void *)0);
    ctx->stack_size = 0;
    ctx->stack_base = 0;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_DONE;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
}


decompiled_code:
__int64 __fastcall concurrent_resume_with_value(__int64 a1, __int64 a2)
{
int v2; // eax

v2 = *(_DWORD *)(a1 + 48);
if ( v2 )
{
if ( v2 != 2 )
concurrent_resume_with_value_cold();
}
else
{
concurrent_setup_execution_context(a1);
}
*(_DWORD *)(a1 + 48) = 1;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = a2;
concurrent_arch_trampoline_to_procedure(a1);
if ( *(_DWORD *)(a1 + 48) != 1 )
return *(_QWORD *)(a1 + 64);
*(_DWORD *)(a1 + 48) = 3;
return 0LL;
}

original_code:
void *
concurrent_resume_with_value(struct concurrent_ctx *ctx, void *value)
{
    switch (ctx->state) {
    case CONCURRENT_STATE_SETUP:
        concurrent_setup_execution_context(ctx);
    case CONCURRENT_STATE_YIELD:
        ctx->state = CONCURRENT_STATE_EXECUTE;
        ctx->yield_value = ((void *)0);
        ctx->resume_value = value;
        concurrent_arch_trampoline_to_procedure(ctx);
        if (ctx->state == CONCURRENT_STATE_EXECUTE) {
            ctx->state = CONCURRENT_STATE_DONE;
            return ((void *)0);
        } else {
            return ctx->yield_value;
        }
    case CONCURRENT_STATE_EXECUTE:
    case CONCURRENT_STATE_DONE:
    default:
        panic();
    }
    return ((void *)0);
}

canonical_original_code:
void *concurrent_resume_with_value(struct concurrent_ctx *ctx, void *value)
{
    switch (ctx->state) {
    case CONCURRENT_STATE_SETUP:
        concurrent_setup_execution_context(ctx);
    case CONCURRENT_STATE_YIELD:
        ctx->state = CONCURRENT_STATE_EXECUTE;
        ctx->yield_value = ((void *)0);
        ctx->resume_value = value;
        concurrent_arch_trampoline_to_procedure(ctx);
        if (ctx->state == CONCURRENT_STATE_EXECUTE) {
            ctx->state = CONCURRENT_STATE_DONE;
            return ((void *)0);
        } else {
            return ctx->yield_value;
        }
    case CONCURRENT_STATE_EXECUTE:
    case CONCURRENT_STATE_DONE:
    default:
        panic();
    }
    return ((void *)0);
}

variable_types:
value
void *

return_type: void *


decompiled_code:
__int64 __fastcall concurrent_resume(__int64 a1)
{
return concurrent_resume_with_value(a1, 0LL);
}

canonical_decompiled_code:
__int64 __fastcall func23(__int64 a1)
{
return func22(a1, 0LL);
}

original_code:
void *
concurrent_resume(struct concurrent_ctx *ctx)
{
    return concurrent_resume_with_value(ctx, ((void *)0));
}

canonical_original_code:
void *concurrent_resume(struct concurrent_ctx *ctx)
{
    return concurrent_resume_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_resume_value(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

canonical_decompiled_code:
__int64 __fastcall func24(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_get_resume_value(struct concurrent_ctx *ctx)
{
    return ctx->resume_value;
}

canonical_original_code:
void *concurrent_get_resume_value(struct concurrent_ctx *ctx)
{
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield_with_value(__int64 a1, __int64 a2)
{
if ( *(_DWORD *)(a1 + 48) != 1 )
concurrent_yield_with_value_cold();
*(_QWORD *)(a1 + 64) = a2;
*(_DWORD *)(a1 + 48) = 2;
concurrent_arch_trampoline_to_caller();
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_yield_with_value(struct concurrent_ctx *ctx, void *value)
{
    if (ctx->state != CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->yield_value = value;
    ctx->state = CONCURRENT_STATE_YIELD;
    concurrent_arch_trampoline_to_caller(ctx);
    return ctx->resume_value;
}

canonical_original_code:
void *concurrent_yield_with_value(struct concurrent_ctx *ctx, void *value)
{
    if (ctx->state != CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->yield_value = value;
    ctx->state = CONCURRENT_STATE_YIELD;
    concurrent_arch_trampoline_to_caller(ctx);
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield(__int64 a1)
{
return concurrent_yield_with_value(a1, 0LL);
}

canonical_decompiled_code:
__int64 __fastcall func26(__int64 a1)
{
return func25(a1, 0LL);
}

original_code:
void *
concurrent_yield(struct concurrent_ctx *ctx)
{
    return concurrent_yield_with_value(ctx, ((void *)0));
}

canonical_original_code:
void *concurrent_yield(struct concurrent_ctx *ctx)
{
    return concurrent_yield_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_yield_value(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

canonical_decompiled_code:
__int64 __fastcall func27(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

original_code:
void *
concurrent_get_yield_value(struct concurrent_ctx *ctx)
{
    return ctx->yield_value;
}

canonical_original_code:
void *concurrent_get_yield_value(struct concurrent_ctx *ctx)
{
    return ctx->yield_value;
}


decompiled_code:
void __fastcall concurrent_reset(__int64 a1)
{
if ( *(_DWORD *)(a1 + 48) == 1 )
concurrent_reset_cold();
*(_DWORD *)(a1 + 48) = 0;
}

original_code:
void
concurrent_reset(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->state = CONCURRENT_STATE_SETUP;
}


decompiled_code:
__int64 __fastcall concurrent_get_user_ptr(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

canonical_decompiled_code:
__int64 __fastcall func29(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

original_code:
void *
concurrent_get_user_ptr(struct concurrent_ctx *ctx)
{
    return ctx->user_ptr;
}

canonical_original_code:
void *concurrent_get_user_ptr(struct concurrent_ctx *ctx)
{
    return ctx->user_ptr;
}


decompiled_code:
bool __fastcall concurrent_is_done(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

canonical_decompiled_code:
bool __fastcall func30(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

original_code:
_Bool
concurrent_is_done(struct concurrent_ctx *ctx)
{
    return (ctx->state == CONCURRENT_STATE_DONE) ? 1 : 0;
}


decompiled_code:
__int64 __fastcall concurrent_get_stack_used(__int64 a1)
{
int v1; // eax

v1 = *(_DWORD *)(a1 + 48);
if ( !v1 )
return 0LL;
if ( v1 == 1 )
concurrent_get_stack_used_cold();
return *(_QWORD *)(a1 + 32) - *(_QWORD *)(a1 + 40);
}

original_code:
size_t
concurrent_get_stack_used(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_SETUP) {
        return 0;
    }
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    return (size_t)(ctx->stack_base - ctx->stack_ptr);
}

canonical_original_code:
unsigned long concurrent_get_stack_used(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_SETUP) {
        return 0;
    }
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    return (unsigned long)(ctx->stack_base - ctx->stack_ptr);
}


decompiled_code:
__int64 __fastcall concurrent_get_stack(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

canonical_decompiled_code:
__int64 __fastcall func32(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

original_code:
void *
concurrent_get_stack(struct concurrent_ctx *ctx)
{
    return ctx->stack_orig;
}

canonical_original_code:
void *concurrent_get_stack(struct concurrent_ctx *ctx)
{
    return ctx->stack_orig;
}


panic

decompiled_code:
void __noreturn panic()
{
abort();
}

canonical_decompiled_code:
void __noreturn func1()
{
abort();
}

original_code:
_Noreturn static void
panic(void)
{
    abort();
}

canonical_original_code:
static void panic()
{
    abort();
}


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rsp
unsigned int *v4; // rax
_BYTE v6[12]; // [rsp+0h] [rbp-820h] BYREF
int i; // [rsp+Ch] [rbp-814h] BYREF
char v8[2056]; // [rsp+10h] [rbp-810h] BYREF

v3 = alloca(concurrent_sizeof(argc, argv, envp));
concurrent_init();
concurrent_construct(v6, v8, 2048LL, accumulator, 0LL);
for ( i = 1; i <= 10; ++i )
{
v4 = (unsigned int *)concurrent_resume_with_value(v6, &i);
printf("total = %d\n", *v4);
}
concurrent_destruct(v6);
concurrent_fin();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rsp
unsigned int *v4; // rax
_BYTE v6[12]; // [rsp+0h] [rbp-820h] BYREF
int i; // [rsp+Ch] [rbp-814h] BYREF
char v8[2056]; // [rsp+10h] [rbp-810h] BYREF

v3 = alloca(concurrent_sizeof(argc, argv, envp));
func14();
func17(v6, v8, 2048LL, accumulator, 0LL);
for ( i = 1; i <= 10; ++i )
{
v4 = (unsigned int *)func19(v6, &i);
printf("total = %d\n", *v4);
}
func18(v6);
func15();
return 0;
}

original_code:
int main(void)
{
    uint8_t *stack;
    const int stack_size = 1024 * 4;
    int data[] = { 12, 13, 14, 15, 10, 9, 7, 1, 2, 11, 3, 4, 8, 6, 5, 0 };
    struct sort_ctx sort_arg;
    sort_arg.data = data;
    sort_arg.num_data = sizeof(data) / sizeof(data[0]);
    concurrent_init();
    g_context = malloc(concurrent_sizeof());
    stack = malloc(sizeof(*stack) * stack_size);
    concurrent_construct(g_context, stack, stack_size, coro, (void *)&sort_arg);
    while (!concurrent_is_done(g_context)) {
        size_t stack_size_used = concurrent_get_stack_used(g_context);
        printf("stack used:%3zdbytes(%2.0f%%); data={ ",
               stack_size_used, ((float)stack_size_used / stack_size) * 100.0f);
        print_datas(&sort_arg);
        printf("}\n");
        concurrent_resume(g_context);
    }
    concurrent_destruct(g_context);
    free(stack);
    free(g_context);
    concurrent_fin();
    return 0;
}

canonical_original_code:
int main()
{
    unsigned char *stack;
    int stack_size = 1024 * 4;
    int data[] = { 12, 13, 14, 15, 10, 9, 7, 1, 2, 11, 3, 4, 8, 6, 5, 0 };
    struct sort_ctx sort_arg;
    sort_arg.data = data;
    sort_arg.num_data = sizeof(data) / sizeof(data[0]);
    concurrent_init();
    g_context = malloc(concurrent_sizeof());
    stack = malloc(sizeof(*stack) * stack_size);
    concurrent_construct(g_context, stack, stack_size, coro, (void *)&sort_arg);
    while (!concurrent_is_done(g_context)) {
        unsigned long stack_size_used = concurrent_get_stack_used(g_context);
        printf("stack used:%3zdbytes(%2.0f%%); data={ ",
               stack_size_used, ((float)stack_size_used / stack_size) * 100.0f);
        print_datas(&sort_arg);
        printf("}\n");
        concurrent_resume(g_context);
    }
    concurrent_destruct(g_context);
    free(stack);
    free(g_context);
    concurrent_fin();
    return 0;
}

variable_types:
stack
unsigned char *

variable_types:
data
int []

variable_types: struct sort_ctx { int *data; int num_data; }

return_type: int


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func13(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

original_code:
static void
concurrent_setup_execution_context(struct concurrent_ctx *ctx)
{
    ctx->stack_ptr = ctx->stack_base;
    concurrent_arch_setup_execution_context(ctx);
}


decompiled_code:
void concurrent_fin()
{
;
}

canonical_decompiled_code:
void func15()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
return 80LL;
}

canonical_decompiled_code:
__int64 func16()
{
return 80LL;
}

original_code:
size_t
concurrent_sizeof(void)
{
    return sizeof(struct concurrent_ctx);
}


decompiled_code:
__int64 __fastcall concurrent_construct(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func17(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

original_code:
concurrent_status
concurrent_construct(struct concurrent_ctx *ctx,
                     void *stack_buffer,
                     size_t stack_size,
                     concurrent_proc proc,
                     void *user_ptr)
{
    const uintptr_t align = 16 - 1;
    uintptr_t aligned_stack_buffer;
    if (ctx && stack_buffer && proc) {
    } else {
        return CONCURRENT_E_INVALID_ARGUMENT;
    }
    if (stack_size < (1024)) {
        return CONCURRENT_E_STACKSIZE_TOO_SMALL;
    }
    aligned_stack_buffer = ((uintptr_t)stack_buffer + align) & ~align;
    (((uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer) ? (void) (0) : __assert_fail ("(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer", "src/concurrent.c", 94, __extension__ __PRETTY_FUNCTION__));
    ctx->proc = proc;
    ctx->user_ptr = user_ptr;
    ctx->stack_orig = stack_buffer;
    ctx->stack_size = (stack_size - (size_t)(aligned_stack_buffer - (uintptr_t)stack_buffer)) & ~(size_t)align;
    ctx->stack_base = aligned_stack_buffer + ctx->stack_size;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_SETUP;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
    return CONCURRENT_SUCCESS;
}

user_defined_types: enum concurrent_status { CONCURRENT_SUCCESS=0, CONCURRENT_E_INVALID_ARGUMENT=1, CONCURRENT_E_STACKSIZE_TOO_SMALL=2 }


original_code:
void
concurrent_destruct(struct concurrent_ctx *ctx)
{
    ctx->proc = ((void *)0);
    ctx->user_ptr = ((void *)0);
    ctx->stack_orig = ((void *)0);
    ctx->stack_size = 0;
    ctx->stack_base = 0;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_DONE;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
}


decompiled_code:
__int64 __fastcall concurrent_resume_with_value(__int64 a1, __int64 a2)
{
int v2; // eax

v2 = *(_DWORD *)(a1 + 48);
if ( v2 )
{
if ( v2 != 2 )
concurrent_resume_with_value_cold();
}
else
{
concurrent_setup_execution_context(a1);
}
*(_DWORD *)(a1 + 48) = 1;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = a2;
concurrent_arch_trampoline_to_procedure(a1);
if ( *(_DWORD *)(a1 + 48) != 1 )
return *(_QWORD *)(a1 + 64);
*(_DWORD *)(a1 + 48) = 3;
return 0LL;
}

original_code:
void *
concurrent_resume_with_value(struct concurrent_ctx *ctx, void *value)
{
    switch (ctx->state) {
    case CONCURRENT_STATE_SETUP:
        concurrent_setup_execution_context(ctx);
    case CONCURRENT_STATE_YIELD:
        ctx->state = CONCURRENT_STATE_EXECUTE;
        ctx->yield_value = ((void *)0);
        ctx->resume_value = value;
        concurrent_arch_trampoline_to_procedure(ctx);
        if (ctx->state == CONCURRENT_STATE_EXECUTE) {
            ctx->state = CONCURRENT_STATE_DONE;
            return ((void *)0);
        } else {
            return ctx->yield_value;
        }
    case CONCURRENT_STATE_EXECUTE:
    case CONCURRENT_STATE_DONE:
    default:
        panic();
    }
    return ((void *)0);
}


decompiled_code:
__int64 __fastcall concurrent_resume(__int64 a1)
{
return concurrent_resume_with_value(a1, 0LL);
}

canonical_decompiled_code:
__int64 __fastcall func20(__int64 a1)
{
return func19(a1, 0LL);
}

original_code:
void *
concurrent_resume(struct concurrent_ctx *ctx)
{
    return concurrent_resume_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_resume_value(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

canonical_decompiled_code:
__int64 __fastcall func21(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_get_resume_value(struct concurrent_ctx *ctx)
{
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield_with_value(__int64 a1, __int64 a2)
{
if ( *(_DWORD *)(a1 + 48) != 1 )
concurrent_yield_with_value_cold();
*(_QWORD *)(a1 + 64) = a2;
*(_DWORD *)(a1 + 48) = 2;
concurrent_arch_trampoline_to_caller();
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_yield_with_value(struct concurrent_ctx *ctx, void *value)
{
    if (ctx->state != CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->yield_value = value;
    ctx->state = CONCURRENT_STATE_YIELD;
    concurrent_arch_trampoline_to_caller(ctx);
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield(__int64 a1)
{
return concurrent_yield_with_value(a1, 0LL);
}

original_code:
void *
concurrent_yield(struct concurrent_ctx *ctx)
{
    return concurrent_yield_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_yield_value(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

canonical_decompiled_code:
__int64 __fastcall func24(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

original_code:
void *
concurrent_get_yield_value(struct concurrent_ctx *ctx)
{
    return ctx->yield_value;
}


decompiled_code:
void __fastcall concurrent_reset(__int64 a1)
{
if ( *(_DWORD *)(a1 + 48) == 1 )
concurrent_reset_cold();
*(_DWORD *)(a1 + 48) = 0;
}

original_code:
void
concurrent_reset(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->state = CONCURRENT_STATE_SETUP;
}


decompiled_code:
__int64 __fastcall concurrent_get_user_ptr(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

canonical_decompiled_code:
__int64 __fastcall func26(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

original_code:
void *
concurrent_get_user_ptr(struct concurrent_ctx *ctx)
{
    return ctx->user_ptr;
}


decompiled_code:
bool __fastcall concurrent_is_done(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

canonical_decompiled_code:
bool __fastcall func27(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

original_code:
_Bool
concurrent_is_done(struct concurrent_ctx *ctx)
{
    return (ctx->state == CONCURRENT_STATE_DONE) ? 1 : 0;
}


decompiled_code:
__int64 __fastcall concurrent_get_stack_used(__int64 a1)
{
int v1; // eax

v1 = *(_DWORD *)(a1 + 48);
if ( !v1 )
return 0LL;
if ( v1 == 1 )
concurrent_get_stack_used_cold();
return *(_QWORD *)(a1 + 32) - *(_QWORD *)(a1 + 40);
}

original_code:
size_t
concurrent_get_stack_used(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_SETUP) {
        return 0;
    }
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    return (size_t)(ctx->stack_base - ctx->stack_ptr);
}


decompiled_code:
__int64 __fastcall concurrent_get_stack(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

canonical_decompiled_code:
__int64 __fastcall func29(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

original_code:
void *
concurrent_get_stack(struct concurrent_ctx *ctx)
{
    return ctx->stack_orig;
}


panic

decompiled_code:
void __noreturn panic()
{
abort();
}

canonical_decompiled_code:
void __noreturn func2()
{
abort();
}

original_code:
_Noreturn static void
panic(void)
{
    abort();
}


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
size_t v4; // rax
void *v5; // rbp
void *v6; // r13
size_t v7; // rax
void *v8; // r12
void *v9; // r14
const char *v11; // [rsp+0h] [rbp-38h] BYREF
const char *v12; // [rsp+8h] [rbp-30h] BYREF

v3 = 10;
concurrent_init(argc, argv, envp);
v4 = concurrent_sizeof();
v5 = malloc(v4);
v11 = "A";
v6 = malloc(0x800uLL);
concurrent_construct(v5, v6, 2048LL, task, &v11);
v7 = concurrent_sizeof();
v8 = malloc(v7);
v9 = malloc(0x800uLL);
v12 = "B";
concurrent_construct(v8, v9, 2048LL, task, &v12);
do
{
puts("main:");
concurrent_resume(v5);
puts("main:");
concurrent_resume(v8);
--v3;
}
while ( v3 );
puts("finish");
concurrent_destruct(v8);
free(v9);
free(v8);
concurrent_destruct(v5);
free(v6);
free(v5);
concurrent_fin();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
size_t v4; // rax
void *v5; // rbp
void *v6; // r13
size_t v7; // rax
void *v8; // r12
void *v9; // r14
const char *v11; // [rsp+0h] [rbp-38h] BYREF
const char *v12; // [rsp+8h] [rbp-30h] BYREF

v3 = 10;
func15(argc, argv, envp);
v4 = func17();
v5 = malloc(v4);
v11 = "A";
v6 = malloc(0x800uLL);
func18(v5, v6, 2048LL, task, &v11);
v7 = func17();
v8 = malloc(v7);
v9 = malloc(0x800uLL);
v12 = "B";
func18(v8, v9, 2048LL, task, &v12);
do
{
puts("main:");
func21(v5);
puts("main:");
func21(v8);
--v3;
}
while ( v3 );
puts("finish");
func19(v8);
free(v9);
free(v8);
func19(v5);
free(v6);
free(v5);
func16();
return 0;
}

original_code:
int main(void)
{
    uint8_t *stack;
    const int stack_size = 1024 * 4;
    int data[] = { 12, 13, 14, 15, 10, 9, 7, 1, 2, 11, 3, 4, 8, 6, 5, 0 };
    struct sort_ctx sort_arg;
    sort_arg.data = data;
    sort_arg.num_data = sizeof(data) / sizeof(data[0]);
    concurrent_init();
    g_context = malloc(concurrent_sizeof());
    stack = malloc(sizeof(*stack) * stack_size);
    concurrent_construct(g_context, stack, stack_size, coro, (void *)&sort_arg);
    while (!concurrent_is_done(g_context)) {
        size_t stack_size_used = concurrent_get_stack_used(g_context);
        printf("stack used:%3zdbytes(%2.0f%%); data={ ",
               stack_size_used, ((float)stack_size_used / stack_size) * 100.0f);
        print_datas(&sort_arg);
        printf("}\n");
        concurrent_resume(g_context);
    }
    concurrent_destruct(g_context);
    free(stack);
    free(g_context);
    concurrent_fin();
    return 0;
}

user_defined_types: struct sort_ctx { int *data; int num_data; }


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func14(__int64 a1)
{
__int64 result; // rax
_QWORD v2[12]; // [rsp-60h] [rbp-60h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)&retaddr);
v2[11] = a1;
v2[10] = a1;
v2[9] = concurrent_arch_return_at_procedure;
v2[8] = *(_QWORD *)(a1 + concurrent_offsetof_procedure);
v2[7] = 0LL;
v2[6] = 0LL;
v2[5] = a1;
v2[4] = 0LL;
v2[3] = 0LL;
v2[2] = 0LL;
v2[1] = 0LL;
v2[0] = 0LL;
result = concurrent_offsetof_stack_ptr;
_InterlockedExchange64((volatile __int64 *)(a1 + concurrent_offsetof_stack_ptr), (__int64)v2);
return result;
}

original_code:
static void
concurrent_setup_execution_context(struct concurrent_ctx *ctx)
{
    ctx->stack_ptr = ctx->stack_base;
    concurrent_arch_setup_execution_context(ctx);
}


decompiled_code:
void concurrent_fin()
{
;
}

canonical_decompiled_code:
void func16()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
return 80LL;
}

canonical_decompiled_code:
__int64 func17()
{
return 80LL;
}

original_code:
size_t
concurrent_sizeof(void)
{
    return sizeof(struct concurrent_ctx);
}


decompiled_code:
__int64 __fastcall concurrent_construct(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func18(__int64 a1, unsigned __int64 a2, unsigned __int64 a3, __int64 a4, __int64 a5)
{
unsigned __int64 v5; // rax
unsigned __int64 v6; // rsi
unsigned __int64 v7; // rsi
__int64 result; // rax

if ( a4 == 0 || a2 == 0 || !a1 )
return 1LL;
if ( a3 <= 0x3FF )
return 2LL;
v5 = (a2 + 15) & 0xFFFFFFFFFFFFFFF0LL;
if ( a2 > v5 )
__assert_fail(
"(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer",
"src/concurrent.c",
0x5Eu,
"concurrent_construct");
*(_QWORD *)(a1 + 16) = a2;
*(_QWORD *)a1 = a4;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 24) = v6;
v7 = v5 + v6;
result = 0LL;
*(_QWORD *)(a1 + 32) = v7;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return result;
}

original_code:
concurrent_status
concurrent_construct(struct concurrent_ctx *ctx,
                     void *stack_buffer,
                     size_t stack_size,
                     concurrent_proc proc,
                     void *user_ptr)
{
    const uintptr_t align = 16 - 1;
    uintptr_t aligned_stack_buffer;
    if (ctx && stack_buffer && proc) {
    } else {
        return CONCURRENT_E_INVALID_ARGUMENT;
    }
    if (stack_size < (1024)) {
        return CONCURRENT_E_STACKSIZE_TOO_SMALL;
    }
    aligned_stack_buffer = ((uintptr_t)stack_buffer + align) & ~align;
    (((uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer) ? (void) (0) : __assert_fail ("(uintptr_t)aligned_stack_buffer >= (uintptr_t)stack_buffer", "src/concurrent.c", 94, __extension__ __PRETTY_FUNCTION__));
    ctx->proc = proc;
    ctx->user_ptr = user_ptr;
    ctx->stack_orig = stack_buffer;
    ctx->stack_size = (stack_size - (size_t)(aligned_stack_buffer - (uintptr_t)stack_buffer)) & ~(size_t)align;
    ctx->stack_base = aligned_stack_buffer + ctx->stack_size;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_SETUP;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
    return CONCURRENT_SUCCESS;
}


original_code:
void
concurrent_destruct(struct concurrent_ctx *ctx)
{
    ctx->proc = ((void *)0);
    ctx->user_ptr = ((void *)0);
    ctx->stack_orig = ((void *)0);
    ctx->stack_size = 0;
    ctx->stack_base = 0;
    ctx->stack_ptr = 0;
    ctx->state = CONCURRENT_STATE_DONE;
    ctx->caller_return_addr = ((void *)0);
    ctx->yield_value = ((void *)0);
    ctx->resume_value = ((void *)0);
}


decompiled_code:
__int64 __fastcall concurrent_resume_with_value(__int64 a1, __int64 a2)
{
int v2; // eax

v2 = *(_DWORD *)(a1 + 48);
if ( v2 )
{
if ( v2 != 2 )
concurrent_resume_with_value_cold();
}
else
{
concurrent_setup_execution_context(a1);
}
*(_DWORD *)(a1 + 48) = 1;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = a2;
concurrent_arch_trampoline_to_procedure(a1);
if ( *(_DWORD *)(a1 + 48) != 1 )
return *(_QWORD *)(a1 + 64);
*(_DWORD *)(a1 + 48) = 3;
return 0LL;
}

original_code:
void *
concurrent_resume_with_value(struct concurrent_ctx *ctx, void *value)
{
    switch (ctx->state) {
    case CONCURRENT_STATE_SETUP:
        concurrent_setup_execution_context(ctx);
    case CONCURRENT_STATE_YIELD:
        ctx->state = CONCURRENT_STATE_EXECUTE;
        ctx->yield_value = ((void *)0);
        ctx->resume_value = value;
        concurrent_arch_trampoline_to_procedure(ctx);
        if (ctx->state == CONCURRENT_STATE_EXECUTE) {
            ctx->state = CONCURRENT_STATE_DONE;
            return ((void *)0);
        } else {
            return ctx->yield_value;
        }
    case CONCURRENT_STATE_EXECUTE:
    case CONCURRENT_STATE_DONE:
    default:
        panic();
    }
    return ((void *)0);
}


decompiled_code:
__int64 __fastcall concurrent_resume(__int64 a1)
{
return concurrent_resume_with_value(a1, 0LL);
}

canonical_decompiled_code:
__int64 __fastcall func21(__int64 a1)
{
return func20(a1, 0LL);
}

original_code:
void *
concurrent_resume(struct concurrent_ctx *ctx)
{
    return concurrent_resume_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_resume_value(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

canonical_decompiled_code:
__int64 __fastcall func22(__int64 a1)
{
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_get_resume_value(struct concurrent_ctx *ctx)
{
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield_with_value(__int64 a1, __int64 a2)
{
if ( *(_DWORD *)(a1 + 48) != 1 )
concurrent_yield_with_value_cold();
*(_QWORD *)(a1 + 64) = a2;
*(_DWORD *)(a1 + 48) = 2;
concurrent_arch_trampoline_to_caller();
return *(_QWORD *)(a1 + 72);
}

original_code:
void *
concurrent_yield_with_value(struct concurrent_ctx *ctx, void *value)
{
    if (ctx->state != CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->yield_value = value;
    ctx->state = CONCURRENT_STATE_YIELD;
    concurrent_arch_trampoline_to_caller(ctx);
    return ctx->resume_value;
}


decompiled_code:
__int64 __fastcall concurrent_yield(__int64 a1)
{
return concurrent_yield_with_value(a1, 0LL);
}

canonical_decompiled_code:
__int64 __fastcall func24(__int64 a1)
{
return func23(a1, 0LL);
}

original_code:
void *
concurrent_yield(struct concurrent_ctx *ctx)
{
    return concurrent_yield_with_value(ctx, ((void *)0));
}


decompiled_code:
__int64 __fastcall concurrent_get_yield_value(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

canonical_decompiled_code:
__int64 __fastcall func25(__int64 a1)
{
return *(_QWORD *)(a1 + 64);
}

original_code:
void *
concurrent_get_yield_value(struct concurrent_ctx *ctx)
{
    return ctx->yield_value;
}


decompiled_code:
void __fastcall concurrent_reset(__int64 a1)
{
if ( *(_DWORD *)(a1 + 48) == 1 )
concurrent_reset_cold();
*(_DWORD *)(a1 + 48) = 0;
}

original_code:
void
concurrent_reset(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    ctx->state = CONCURRENT_STATE_SETUP;
}


decompiled_code:
__int64 __fastcall concurrent_get_user_ptr(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

canonical_decompiled_code:
__int64 __fastcall func27(__int64 a1)
{
return *(_QWORD *)(a1 + 8);
}

original_code:
void *
concurrent_get_user_ptr(struct concurrent_ctx *ctx)
{
    return ctx->user_ptr;
}


decompiled_code:
bool __fastcall concurrent_is_done(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

canonical_decompiled_code:
bool __fastcall func28(__int64 a1)
{
return *(_DWORD *)(a1 + 48) == 3;
}

original_code:
_Bool
concurrent_is_done(struct concurrent_ctx *ctx)
{
    return (ctx->state == CONCURRENT_STATE_DONE) ? 1 : 0;
}


decompiled_code:
__int64 __fastcall concurrent_get_stack_used(__int64 a1)
{
int v1; // eax

v1 = *(_DWORD *)(a1 + 48);
if ( !v1 )
return 0LL;
if ( v1 == 1 )
concurrent_get_stack_used_cold();
return *(_QWORD *)(a1 + 32) - *(_QWORD *)(a1 + 40);
}

original_code:
size_t
concurrent_get_stack_used(struct concurrent_ctx *ctx)
{
    if (ctx->state == CONCURRENT_STATE_SETUP) {
        return 0;
    }
    if (ctx->state == CONCURRENT_STATE_EXECUTE) {
        panic();
    }
    return (size_t)(ctx->stack_base - ctx->stack_ptr);
}


decompiled_code:
__int64 __fastcall concurrent_get_stack(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

canonical_decompiled_code:
__int64 __fastcall func30(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

original_code:
void *
concurrent_get_stack(struct concurrent_ctx *ctx)
{
    return ctx->stack_orig;
}


repo: sharvil/flingfd

decompiled_code:
int __fastcall flingfd_send(__int64 a1, int a2)
{
_DWORD *v4; // rax
int v5; // edi
int result; // eax
const char *v7; // rsi
int v8; // edi
__int64 v9; // [rsp+0h] [rbp-B8h] BYREF
char v10[32]; // [rsp+10h] [rbp-A8h] BYREF
struct msghdr message; // [rsp+30h] [rbp-88h] BYREF
char v12; // [rsp+9Dh] [rbp-1Bh]

if ( !a1 || a2 == -1 )
{
*_errno_location() = 22;
return -1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v7 = *(const char **)(a1 + 8);
LOWORD(message.msg_name) = 1;
strncpy((char *)&message.msg_name + 2, v7, 0x6BuLL);
v8 = *(_DWORD *)a1;
v12 = 0;
result = connect(v8, (const struct sockaddr *)&message, 0x6Eu);
if ( result == -1 )
return result;
*(_BYTE *)(a1 + 16) = 1;
}
flingfd_init_msg__constprop_0((__int64)&message, &v9, (__int64)v10);
if ( message.msg_controllen <= 0xF )
flingfd_send_cold();
v4 = message.msg_control;
*((_QWORD *)message.msg_control + 1) = 0x100000001LL;
v4[4] = a2;
v5 = *(_DWORD *)a1;
*(_QWORD *)v4 = 20LL;
return sendmsg(v5, &message, 0);
}

canonical_decompiled_code:
int __fastcall func1(__int64 a1, int a2)
{
_DWORD *v4; // rax
int v5; // edi
int result; // eax
const char *v7; // rsi
int v8; // edi
__int64 v9; // [rsp+0h] [rbp-B8h] BYREF
char v10[32]; // [rsp+10h] [rbp-A8h] BYREF
struct msghdr message; // [rsp+30h] [rbp-88h] BYREF
char v12; // [rsp+9Dh] [rbp-1Bh]

if ( !a1 || a2 == -1 )
{
*_errno_location() = 22;
return -1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v7 = *(const char **)(a1 + 8);
LOWORD(message.msg_name) = 1;
strncpy((char *)&message.msg_name + 2, v7, 0x6BuLL);
v8 = *(_DWORD *)a1;
v12 = 0;
result = connect(v8, (const struct sockaddr *)&message, 0x6Eu);
if ( result == -1 )
return result;
*(_BYTE *)(a1 + 16) = 1;
}
func0((__int64)&message, &v9, (__int64)v10);
if ( message.msg_controllen <= 0xF )
func8();
v4 = message.msg_control;
*((_QWORD *)message.msg_control + 1) = 0x100000001LL;
v4[4] = a2;
v5 = *(_DWORD *)a1;
*(_QWORD *)v4 = 20LL;
return sendmsg(v5, &message, 0);
}

original_code:
int flingfd_send(flingfd_t *handle, int fd) {
  if (!handle || fd == -1) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    if (connect(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0);
  header->cmsg_level = 1;
  header->cmsg_type = SCM_RIGHTS;
  header->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (sizeof(int)));
  *(int *)((header)->__cmsg_data) = fd;
  return sendmsg(handle->fd, &msg, 0);
}

canonical_original_code:
int flingfd_send(struct flingfd_t *handle, int fd) {
  if (!handle || fd == -1) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    if (connect(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[-1];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0);
  header->cmsg_level = 1;
  header->cmsg_type = SCM_RIGHTS;
  header->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (unsigned long) - 1) & (unsigned long) ~(sizeof (unsigned long) - 1)) + (sizeof(int)));
  *(int *)((header)->__cmsg_data) = fd;
  return sendmsg(handle->fd, &msg, 0);
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; } *

variable_types: fd int

variable_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

variable_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec { void *iov_base; unsigned long iov_len; } *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }

variable_types:
buf
char [-1]

variable_types: struct cmsghdr { unsigned long cmsg_len; int cmsg_level; int cmsg_type; unsigned char __cmsg_data[]; } *

user_defined_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }

user_defined_types: struct sockaddr { unsigned short sa_family; char sa_data[14]; }


decompiled_code:
bool __fastcall flingfd_socket_send(int a1, int a2)
{
int v3; // [rsp+0h] [rbp-28h] BYREF
__int64 v4; // [rsp+8h] [rbp-20h]
char v5; // [rsp+10h] [rbp-18h]

v3 = a1;
v4 = 0LL;
v5 = 1;
return flingfd_send((__int64)&v3, a2) != -1;
}

canonical_decompiled_code:
bool __fastcall func2(int a1, int a2)
{
int v3; // [rsp+0h] [rbp-28h] BYREF
__int64 v4; // [rsp+8h] [rbp-20h]
char v5; // [rsp+10h] [rbp-18h]

v3 = a1;
v4 = 0LL;
v5 = 1;
return func1((__int64)&v3, a2) != -1;
}

original_code:
_Bool flingfd_socket_send(int socket_fd, int fd) {
  flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_send(&handle, fd) != -1;
}

canonical_original_code:
_Bool flingfd_socket_send(int socket_fd, int fd) {
  struct flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_send(&handle, fd) != -1;
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; }


decompiled_code:
__int64 __fastcall flingfd_recv(__int64 a1)
{
char *v1; // rbp
unsigned int v2; // er12
unsigned __int64 v3; // rax
int *v4; // r14
__int64 v5; // r15
const char *v6; // rsi
int v8; // edi
char v9; // [rsp+Fh] [rbp-D9h]
__int64 v10; // [rsp+10h] [rbp-D8h] BYREF
char v11[32]; // [rsp+20h] [rbp-C8h] BYREF
struct msghdr message; // [rsp+40h] [rbp-A8h] BYREF
char v13; // [rsp+ADh] [rbp-3Bh]

if ( !a1 )
{
v2 = -1;
*_errno_location() = 22;
return v2;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v6 = *(const char **)(a1 + 8);
LOWORD(message.msg_name) = 1;
strncpy((char *)&message.msg_name + 2, v6, 0x6BuLL);
v13 = 0;
unlink((const char *)&message.msg_name + 2);
v2 = bind(*(_DWORD *)a1, (const struct sockaddr *)&message, 0x6Eu);
if ( v2 == -1 )
return v2;
*(_BYTE *)(a1 + 16) = 1;
}
flingfd_init_msg__constprop_0((__int64)&message, &v10, (__int64)v11);
if ( recvmsg(*(_DWORD *)a1, &message, 0) == -1 )
return (unsigned int)-1;
if ( message.msg_controllen <= 0xF )
goto LABEL_19;
v1 = (char *)message.msg_control;
v9 = 0;
v2 = -1;
if ( !message.msg_control )
goto LABEL_19;
do
{
if ( *((_QWORD *)v1 + 1) == 0x100000001LL )
{
v3 = (unsigned __int64)(*(_QWORD *)v1 - 16LL) >> 2;
if ( (int)v3 > 0 )
{
v4 = (int *)(v1 + 16);
v5 = (__int64)&v1[4 * (unsigned int)(v3 - 1) + 20];
do
{
if ( v2 == -1 )
{
v2 = *v4;
}
else
{
close(*v4);
v9 = 1;
}
++v4;
}
while ( (int *)v5 != v4 );
}
}
v1 = (char *)_cmsg_nxthdr(&message, (struct cmsghdr *)v1);
}
while ( v1 );
if ( v9 )
{
v8 = v2;
v2 = -1;
close(v8);
*_errno_location() = 74;
return v2;
}
if ( v2 == -1 )
{
LABEL_19:
v2 = -1;
*_errno_location() = 2;
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
char *v1; // rbp
unsigned int v2; // er12
unsigned __int64 v3; // rax
int *v4; // r14
__int64 v5; // r15
const char *v6; // rsi
int v8; // edi
char v9; // [rsp+Fh] [rbp-D9h]
__int64 v10; // [rsp+10h] [rbp-D8h] BYREF
char v11[32]; // [rsp+20h] [rbp-C8h] BYREF
struct msghdr message; // [rsp+40h] [rbp-A8h] BYREF
char v13; // [rsp+ADh] [rbp-3Bh]

if ( !a1 )
{
v2 = -1;
*_errno_location() = 22;
return v2;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v6 = *(const char **)(a1 + 8);
LOWORD(message.msg_name) = 1;
strncpy((char *)&message.msg_name + 2, v6, 0x6BuLL);
v13 = 0;
unlink((const char *)&message.msg_name + 2);
v2 = bind(*(_DWORD *)a1, (const struct sockaddr *)&message, 0x6Eu);
if ( v2 == -1 )
return v2;
*(_BYTE *)(a1 + 16) = 1;
}
func0((__int64)&message, &v10, (__int64)v11);
if ( recvmsg(*(_DWORD *)a1, &message, 0) == -1 )
return (unsigned int)-1;
if ( message.msg_controllen <= 0xF )
goto LABEL_19;
v1 = (char *)message.msg_control;
v9 = 0;
v2 = -1;
if ( !message.msg_control )
goto LABEL_19;
do
{
if ( *((_QWORD *)v1 + 1) == 0x100000001LL )
{
v3 = (unsigned __int64)(*(_QWORD *)v1 - 16LL) >> 2;
if ( (int)v3 > 0 )
{
v4 = (int *)(v1 + 16);
v5 = (__int64)&v1[4 * (unsigned int)(v3 - 1) + 20];
do
{
if ( v2 == -1 )
{
v2 = *v4;
}
else
{
close(*v4);
v9 = 1;
}
++v4;
}
while ( (int *)v5 != v4 );
}
}
v1 = (char *)_cmsg_nxthdr(&message, (struct cmsghdr *)v1);
}
while ( v1 );
if ( v9 )
{
v8 = v2;
v2 = -1;
close(v8);
*_errno_location() = 74;
return v2;
}
if ( v2 == -1 )
{
LABEL_19:
v2 = -1;
*_errno_location() = 2;
}
return v2;
}

original_code:
int flingfd_recv(flingfd_t *handle) {
  if (!handle) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    unlink(addr.sun_path);
    if (bind(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  if (recvmsg(handle->fd, &msg, 0) == -1)
    return -1;
  int found_fd = -1;
  _Bool oh_noes = 0;
  for (struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0); header != ((void *)0); header = __cmsg_nxthdr (&msg, header))
    if (header->cmsg_level == 1 && header->cmsg_type == SCM_RIGHTS) {
      int count = (header->cmsg_len - (((header)->__cmsg_data) - (unsigned char *)header)) / sizeof(int);
      for (int i = 0; i < count; ++i) {
        int fd = ((int *)((header)->__cmsg_data))[i];
        if (found_fd == -1) {
          found_fd = fd;
        } else {
          close(fd);
          oh_noes = 1;
        }
      }
    }
  if (oh_noes) {
    close(found_fd);
    (*__errno_location ()) = 74;
    return -1;
  }
  if (found_fd == -1)
    (*__errno_location ()) = 2;
  return found_fd;
}

canonical_original_code:
int flingfd_recv(struct flingfd_t *handle) {
  if (!handle) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    unlink(addr.sun_path);
    if (bind(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[-1];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  if (recvmsg(handle->fd, &msg, 0) == -1)
    return -1;
  int found_fd = -1;
  _Bool oh_noes = 0;
  for (struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0); header != ((void *)0); header = __cmsg_nxthdr (&msg, header))
    if (header->cmsg_level == 1 && header->cmsg_type == SCM_RIGHTS) {
      int count = (header->cmsg_len - (((header)->__cmsg_data) - (unsigned char *)header)) / sizeof(int);
      for (int i = 0; i < count; ++i) {
        int fd = ((int *)((header)->__cmsg_data))[i];
        if (found_fd == -1) {
          found_fd = fd;
        } else {
          close(fd);
          oh_noes = 1;
        }
      }
    }
  if (oh_noes) {
    close(found_fd);
    (*__errno_location ()) = 74;
    return -1;
  }
  if (found_fd == -1)
    (*__errno_location ()) = 2;
  return found_fd;
}

variable_types: struct iovec { void *iov_base; unsigned long iov_len; }

variable_types: count int

variable_types: i int

user_defined_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

user_defined_types: struct flingfd_t { int fd; char *path; _Bool is_bound; }

user_defined_types: struct cmsghdr { unsigned long cmsg_len; int cmsg_level; int cmsg_type; unsigned char __cmsg_data[]; }


decompiled_code:
__int64 __fastcall flingfd_socket_recv(int a1)
{
int v2; // [rsp+0h] [rbp-28h] BYREF
__int64 v3; // [rsp+8h] [rbp-20h]
char v4; // [rsp+10h] [rbp-18h]

v2 = a1;
v3 = 0LL;
v4 = 1;
return flingfd_recv((__int64)&v2);
}

canonical_decompiled_code:
__int64 __fastcall func4(int a1)
{
int v2; // [rsp+0h] [rbp-28h] BYREF
__int64 v3; // [rsp+8h] [rbp-20h]
char v4; // [rsp+10h] [rbp-18h]

v2 = a1;
v3 = 0LL;
v4 = 1;
return func3((__int64)&v2);
}

original_code:
int flingfd_socket_recv(int socket_fd) {
  flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_recv(&handle);
}

canonical_original_code:
int flingfd_socket_recv(int socket_fd) {
  struct flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_recv(&handle);
}


decompiled_code:
void __fastcall flingfd_close(void **a1)
{
void *v1; // rax

if ( a1 )
{
v1 = *a1;
if ( *a1 )
{
if ( *(_DWORD *)v1 != -1 )
{
close(*(_DWORD *)v1);
v1 = *a1;
}
free(*((void **)v1 + 1));
free(*a1);
*a1 = 0LL;
}
}
}

original_code:
void flingfd_close(flingfd_t **handle) {
  if (handle == ((void *)0) || *handle == ((void *)0))
    return;
  if ((*handle)->fd != -1)
    close((*handle)->fd);
  free((*handle)->path);
  free(*handle);
  *handle = ((void *)0);
}

canonical_original_code:
void flingfd_close(struct flingfd_t **handle) {
  if (handle == ((void *)0) || *handle == ((void *)0))
    return;
  if ((*handle)->fd != -1)
    close((*handle)->fd);
  free((*handle)->path);
  free(*handle);
  *handle = ((void *)0);
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; } **


decompiled_code:
__int64 __fastcall flingfd_simple_send(char *a1, int a2)
{
unsigned int v2; // er12
_QWORD *v3; // rax
void *v5; // [rsp+8h] [rbp-20h] BYREF

v2 = 0;
v3 = flingfd_open(a1);
v5 = v3;
if ( v3 )
{
LOBYTE(v2) = flingfd_send((__int64)v3, a2) != -1;
flingfd_close(&v5);
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func6(char *a1, int a2)
{
unsigned int v2; // er12
_QWORD *v3; // rax
void *v5; // [rsp+8h] [rbp-20h] BYREF

v2 = 0;
v3 = flingfd_open(a1);
v5 = v3;
if ( v3 )
{
LOBYTE(v2) = func1((__int64)v3, a2) != -1;
func5(&v5);
}
return v2;
}

original_code:
_Bool flingfd_simple_send(const char *path, int fd) {
  flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return 0;
  _Bool success = (flingfd_send(handle, fd) != -1);
  flingfd_close(&handle);
  return success;
}

canonical_original_code:
_Bool flingfd_simple_send(char *path, int fd) {
  struct flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return 0;
  _Bool success = (flingfd_send(handle, fd) != -1);
  flingfd_close(&handle);
  return success;
}

variable_types:
path
char *


decompiled_code:
__int64 __fastcall flingfd_simple_recv(char *a1)
{
_QWORD *v1; // rax
unsigned int v2; // er12
void *v4; // [rsp+8h] [rbp-10h] BYREF

v1 = flingfd_open(a1);
v4 = v1;
if ( !v1 )
return (unsigned int)-1;
v2 = flingfd_recv((__int64)v1);
flingfd_close(&v4);
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func7(char *a1)
{
_QWORD *v1; // rax
unsigned int v2; // er12
void *v4; // [rsp+8h] [rbp-10h] BYREF

v1 = flingfd_open(a1);
v4 = v1;
if ( !v1 )
return (unsigned int)-1;
v2 = func3((__int64)v1);
func5(&v4);
return v2;
}

original_code:
int flingfd_simple_recv(const char *path) {
  flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return -1;
  int ret = flingfd_recv(handle);
  flingfd_close(&handle);
  return ret;
}

canonical_original_code:
int flingfd_simple_recv(char *path) {
  struct flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return -1;
  int ret = flingfd_recv(handle);
  flingfd_close(&handle);
  return ret;
}

variable_types: ret int


decompiled_code:
__int64 __fastcall is_power_of_two(int a1)
{
return ((a1 & (a1 - 1)) == 0) & (unsigned __int8)(a1 > 0);
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1)
{
return ((a1 & (a1 - 1)) == 0) & (unsigned __int8)(a1 > 0);
}

original_code:
static int
is_power_of_two(int val)
{
        return ((((val)&(val-1)) == 0) && (val > 0));
}

variable_types: val int


decompiled_code:
int print_info()
{
puts("**** Runtime parameters ****");
printf("Grid size is: %d x %d\n", (unsigned int)gs_size, (unsigned int)gs_size);
printf("Iterations : %d\n", (unsigned int)gs_iterations);
printf("Tolerance : %f\n", *(double *)&gs_tolerance);
printf("Pad = %d elements\n", (unsigned int)gs_pad);
if ( gsi_is_parallel )
printf("Number of threads : %d\n", (unsigned int)gs_nthreads);
printf("Matrix using %dx%d * sizeof(double) bytes of memory\n", (unsigned int)gs_size, (unsigned int)gs_width);
return puts("*****************************");
}

canonical_decompiled_code:
int func2()
{
puts("**** Runtime parameters ****");
printf("Grid size is: %d x %d\n", (unsigned int)gs_size, (unsigned int)gs_size);
printf("Iterations : %d\n", (unsigned int)gs_iterations);
printf("Tolerance : %f\n", *(double *)&gs_tolerance);
printf("Pad = %d elements\n", (unsigned int)gs_pad);
if ( gsi_is_parallel )
printf("Number of threads : %d\n", (unsigned int)gs_nthreads);
printf("Matrix using %dx%d * sizeof(double) bytes of memory\n", (unsigned int)gs_size, (unsigned int)gs_width);
return puts("*****************************");
}

original_code:
static void
print_info()
{
        printf("****  Runtime parameters ****\n");
        printf("Grid size is: %d x %d\n", gs_size, gs_size);
        printf("Iterations : %d\n", gs_iterations);
        printf("Tolerance : %f\n", gs_tolerance);
        printf("Pad = %d elements\n", gs_pad);
        if (gsi_is_parallel)
                printf("Number of threads : %d\n", gs_nthreads);
        printf("Matrix using %dx%d * sizeof(double) bytes of memory\n",
               gs_size, gs_width);
        printf("*****************************\n");
}


decompiled_code:
int gs_verbose_printf(const char *a1, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, a1);
result = gs_verbose;
if ( gs_verbose )
result = vprintf(a1, arg);
return result;
}

canonical_decompiled_code:
int func3(const char *a1, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, a1);
result = gs_verbose;
if ( gs_verbose )
result = vprintf(a1, arg);
return result;
}

original_code:
void
gs_verbose_printf(const char *fmt, ...)
{
        va_list ap;
        __builtin_va_start(ap,fmt);
        if (gs_verbose)
                vprintf(fmt, ap);
        __builtin_va_end(ap);
}

canonical_original_code:
void gs_verbose_printf(char *fmt, ...)
{
        __builtin_va_list ap;
        __builtin_va_start(ap,fmt);
        if (gs_verbose)
                vprintf(fmt, ap);
        __builtin_va_end(ap);
}

variable_types:
fmt
char *


decompiled_code:
size_t __fastcall run_gs(double a1)
{
char v2[24]; // [rsp+10h] [rbp-18h] BYREF

gs_verbose_printf("\t**** Initializing... ****\n");
if ( posix_memalign(&gs_matrix, 0x1000uLL, 8LL * gs_width * gs_size) )
{
fwrite("Error: Failed to allocate memory for matrix.\n", 1uLL, 0x2DuLL, stderr);
exit(1);
}
init_matrix();
gsi_init();
gs_verbose_printf("\t**** Running GS... ****\n");
timing_start(v2);
gsi_calculate();
timing_stop(v2);
if ( gs_output )
write_matrix(gs_output);
gs_verbose_printf("\t**** Cleaning up... ****\n");
gsi_finish();
free(gs_matrix);
fwrite("**** Summary ****\n", 1uLL, 0x12uLL, stdout);
fprintf(stdout, " Execution time: %f s\n", a1);
return fwrite("*****************\n", 1uLL, 0x12uLL, stdout);
}

canonical_decompiled_code:
size_t __fastcall func6(double a1)
{
char v2[24]; // [rsp+10h] [rbp-18h] BYREF

func3("\t**** Initializing... ****\n");
if ( posix_memalign(&gs_matrix, 0x1000uLL, 8LL * gs_width * gs_size) )
{
fwrite("Error: Failed to allocate memory for matrix.\n", 1uLL, 0x2DuLL, stderr);
exit(1);
}
func4();
gsi_init();
func3("\t**** Running GS... ****\n");
timing_start(v2);
gsi_calculate();
timing_stop(v2);
if ( gs_output )
func5(gs_output);
func3("\t**** Cleaning up... ****\n");
gsi_finish();
free(gs_matrix);
fwrite("**** Summary ****\n", 1uLL, 0x12uLL, stdout);
fprintf(stdout, " Execution time: %f s\n", a1);
return fwrite("*****************\n", 1uLL, 0x12uLL, stdout);
}

original_code:
static void
run_gs()
{
        struct timespec ts;
        double exec_time;
        gs_verbose_printf("\t****  Initializing...  ****\n");
                if (posix_memalign((void **)&gs_matrix, 0x1000,
                                   gs_size * gs_width * sizeof(double)) != 0) {
                        fprintf(stderr,
                                "Error: Failed to allocate memory for matrix.\n");
                        exit(1);
                }
                init_matrix();
                gsi_init();
                gs_verbose_printf("\t****  Running GS...  ****\n");
                timing_start(&ts);
                gsi_calculate();
                exec_time = timing_stop(&ts);
                if (gs_output)
                        write_matrix(gs_output);
                gs_verbose_printf("\t****  Cleaning up...  ****\n");
                gsi_finish();
                free(gs_matrix);
                fprintf(stdout,"**** Summary ****\n");
                fprintf(stdout,"   Execution time: %f s\n", exec_time);
                fprintf(stdout,"*****************\n");
        }

variable_types: struct timespec { long tv_sec; long tv_nsec; }


decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
double v3; // xmm0_8
int v4; // er12
int v5; // eax
int v6; // eax

v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vhi:e:s:t:p:o:");
if ( v5 == -1 )
break;
switch ( v5 )
{
case ':':
v4 = 1;
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
break;
case '?':
v4 = 1;
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
break;
case 'e':
v3 = atof(optarg);
gs_tolerance = *(_QWORD *)&v3;
break;
case 'h':
usage(stdout, *argv);
exit(0);
case 'i':
gs_iterations = atoi(optarg);
if ( gs_iterations <= 0 )
{
v4 = 1;
fwrite("Number of iterations must be strictly greater than 1.\n", 1uLL, 0x36uLL, stderr);
}
break;
case 'o':
gs_output = fopen(optarg, "w");
if ( !gs_output )
{
v4 = 1;
perror("Failed to open output");
}
break;
case 'p':
gs_pad = atoi(optarg);
if ( gs_pad < 0 )
{
v4 = 1;
fwrite("Padding must be greater or equal to 0.\n", 1uLL, 0x27uLL, stderr);
}
break;
case 's':
gs_size = atoi(optarg);
if ( gs_size <= 0 )
{
v4 = 1;
fwrite("Size must be larger than 1.\n", 1uLL, 0x1CuLL, stderr);
}
else if ( !(unsigned int)is_power_of_two(gs_size) )
{
v4 = 1;
fwrite("Size is not a power of two.\n", 1uLL, 0x1CuLL, stderr);
}
break;
case 't':
v6 = atoi(optarg);
gs_nthreads = v6;
if ( gsi_is_parallel )
{
if ( v6 <= 0 )
{
v4 = 1;
fwrite("Number of threads must be positive.\n", 1uLL, 0x24uLL, stderr);
}
else if ( !(unsigned int)is_power_of_two(v6) )
{
v4 = 1;
fwrite("Number is not a power of two.\n", 1uLL, 0x1EuLL, stderr);
}
}
else
{
v4 = 1;
fwrite("This is the sequential version -- -t doesn't make sense!\n", 1uLL, 0x39uLL, stderr);
}
break;
case 'v':
gs_verbose = 1;
break;
default:
abort();
}
}
if ( v4 )
{
usage(stderr, *argv);
exit(1);
}
gs_width = gs_size + gs_pad;
if ( gs_verbose )
print_info();
run_gs(v3);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
double v3; // xmm0_8
int v4; // er12
int v5; // eax
int v6; // eax

v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vhi:e:s:t:p:o:");
if ( v5 == -1 )
break;
switch ( v5 )
{
case ':':
v4 = 1;
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
break;
case '?':
v4 = 1;
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
break;
case 'e':
v3 = atof(optarg);
gs_tolerance = *(_QWORD *)&v3;
break;
case 'h':
func1(stdout, *argv);
exit(0);
case 'i':
gs_iterations = atoi(optarg);
if ( gs_iterations <= 0 )
{
v4 = 1;
fwrite("Number of iterations must be strictly greater than 1.\n", 1uLL, 0x36uLL, stderr);
}
break;
case 'o':
gs_output = fopen(optarg, "w");
if ( !gs_output )
{
v4 = 1;
perror("Failed to open output");
}
break;
case 'p':
gs_pad = atoi(optarg);
if ( gs_pad < 0 )
{
v4 = 1;
fwrite("Padding must be greater or equal to 0.\n", 1uLL, 0x27uLL, stderr);
}
break;
case 's':
gs_size = atoi(optarg);
if ( gs_size <= 0 )
{
v4 = 1;
fwrite("Size must be larger than 1.\n", 1uLL, 0x1CuLL, stderr);
}
else if ( !(unsigned int)func0(gs_size) )
{
v4 = 1;
fwrite("Size is not a power of two.\n", 1uLL, 0x1CuLL, stderr);
}
break;
case 't':
v6 = atoi(optarg);
gs_nthreads = v6;
if ( gsi_is_parallel )
{
if ( v6 <= 0 )
{
v4 = 1;
fwrite("Number of threads must be positive.\n", 1uLL, 0x24uLL, stderr);
}
else if ( !(unsigned int)func0(v6) )
{
v4 = 1;
fwrite("Number is not a power of two.\n", 1uLL, 0x1EuLL, stderr);
}
}
else
{
v4 = 1;
fwrite("This is the sequential version -- -t doesn't make sense!\n", 1uLL, 0x39uLL, stderr);
}
break;
case 'v':
gs_verbose = 1;
break;
default:
abort();
}
}
if ( v4 )
{
func1(stderr, *argv);
exit(1);
}
gs_width = gs_size + gs_pad;
if ( gs_verbose )
func2();
func6(v3);
return 0;
}

original_code:
int
                main(int argc, char *argv[])
        {
                int c;
                int errexit = 0;
                extern char *optarg;
                extern int optind, optopt, opterr;
                while ((c = getopt(argc, argv, "vhi:e:s:t:p:o:")) != -1) {
                        switch (c) {
                        case 'v':
                                gs_verbose = 1;
                                break;
                        case 'i':
                                gs_iterations = atoi(optarg);
                                if (gs_iterations <= 0) {
                                        fprintf(stderr,
                                                "Number of iterations must be "
                                                "strictly greater than 1.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'e':
                                gs_tolerance = atof(optarg);
                                break;
                        case 's':
                                gs_size = atoi(optarg);
                                if (gs_size <= 0) {
                                        fprintf(stderr,
                                                "Size must be larger than 1.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_size)) {
                                        fprintf(stderr,
                                                "Size is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 't':
                                gs_nthreads = atoi(optarg);
                                if (!gsi_is_parallel) {
                                        fprintf(stderr,
                                                "This is the sequential version "
                                                "-- -t doesn't make sense!\n");
                                        errexit = 1;
                                } else if (gs_nthreads <= 0) {
                                        fprintf(stderr,
                                                "Number of threads must be "
                                                "positive.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_nthreads)) {
                                        fprintf(stderr,
                                                "Number is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'p':
                                gs_pad = atoi(optarg);
                                if (gs_pad < 0) {
                                        fprintf(stderr,
                                                "Padding must be greater or equal "
                                                "to 0.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'o':
                                gs_output = fopen(optarg, "w");
                                if (!gs_output) {
                                        perror("Failed to open output");
                                        errexit = 1;
                                }
                                break;
                        case 'h':
                                usage(stdout, argv[0]);
                                exit(0);
                        case ':':
                                fprintf(stderr,
                                        "%s: option -%c requries an operand\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        case '?':
                                fprintf(stderr,
                                        "%s: illegal option -- %c\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        default:
                                abort();
                        }
                }
                if (errexit) {
                        usage(stderr, argv[0]);
                        exit(1);
                }
                gs_width = gs_size + gs_pad;
                if (gs_verbose)
                        print_info();
                run_gs();
                return 0;
        }

canonical_original_code:
int main(int argc, char *argv[])
        {
                int c;
                int errexit = 0;
                extern char *optarg;
                extern int optind; extern int optopt; extern int opterr;
                while ((c = getopt(argc, argv, "vhi:e:s:t:p:o:")) != -1) {
                        switch (c) {
                        case 'v':
                                gs_verbose = 1;
                                break;
                        case 'i':
                                gs_iterations = atoi(optarg);
                                if (gs_iterations <= 0) {
                                        fprintf(stderr,
                                                "Number of iterations must be "
                                                "strictly greater than 1.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'e':
                                gs_tolerance = atof(optarg);
                                break;
                        case 's':
                                gs_size = atoi(optarg);
                                if (gs_size <= 0) {
                                        fprintf(stderr,
                                                "Size must be larger than 1.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_size)) {
                                        fprintf(stderr,
                                                "Size is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 't':
                                gs_nthreads = atoi(optarg);
                                if (!gsi_is_parallel) {
                                        fprintf(stderr,
                                                "This is the sequential version "
                                                "-- -t doesn't make sense!\n");
                                        errexit = 1;
                                } else if (gs_nthreads <= 0) {
                                        fprintf(stderr,
                                                "Number of threads must be "
                                                "positive.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_nthreads)) {
                                        fprintf(stderr,
                                                "Number is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'p':
                                gs_pad = atoi(optarg);
                                if (gs_pad < 0) {
                                        fprintf(stderr,
                                                "Padding must be greater or equal "
                                                "to 0.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'o':
                                gs_output = fopen(optarg, "w");
                                if (!gs_output) {
                                        perror("Failed to open output");
                                        errexit = 1;
                                }
                                break;
                        case 'h':
                                usage(stdout, argv[0]);
                                exit(0);
                        case ':':
                                fprintf(stderr,
                                        "%s: option -%c requries an operand\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        case '?':
                                fprintf(stderr,
                                        "%s: illegal option -- %c\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        default:
                                abort();
                        }
                }
                if (errexit) {
                        usage(stderr, argv[0]);
                        exit(1);
                }
                gs_width = gs_size + gs_pad;
                if (gs_verbose)
                        print_info();
                run_gs();
                return 0;
        }

variable_types: argc int

variable_types:
argv
char *[]

variable_types: c int

variable_types: errexit int

variable_types:
optarg
char *

variable_types: optind int

variable_types: optopt int

variable_types: opterr int


decompiled_code:
int __fastcall monotonic_time(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

canonical_decompiled_code:
int __fastcall func0(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

original_code:
static void
monotonic_time(struct timespec *ts)
{
        if (clock_gettime(1, ts) != 0) {
                perror("clock_gettime failed");
                abort();
        }
}

variable_types: struct timespec { long tv_sec; long tv_nsec; } *


decompiled_code:
double __fastcall time_diff(__int64 *a1, __int64 *a2)
{
__int64 v2; // rax
__int64 v3; // rdx
__int64 v4; // rsi

v2 = *a2;
if ( *a2 > *a1 )
{
v3 = a2[1];
v4 = a1[1];
}
else if ( *a2 != *a1 || (v3 = a2[1], v4 = a1[1], v3 < v4) )
{
_assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"lab2.c",
0x4Fu,
"time_diff");
}
return (double)((int)v3 - (int)v4) * 0.000000001 + (double)(int)(v2 - *a1);
}

canonical_decompiled_code:
double __fastcall func1(__int64 *a1, __int64 *a2)
{
__int64 v2; // rax
__int64 v3; // rdx
__int64 v4; // rsi

v2 = *a2;
if ( *a2 > *a1 )
{
v3 = a2[1];
v4 = a1[1];
}
else if ( *a2 != *a1 || (v3 = a2[1], v4 = a1[1], v3 < v4) )
{
_assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"lab2.c",
0x4Fu,
"time_diff");
}
return (double)((int)v3 - (int)v4) * 0.000000001 + (double)(int)(v2 - *a1);
}

original_code:
static double
time_diff(struct timespec *ts_start, struct timespec *ts_stop)
{
        ((ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)) ? (void) (0) : __assert_fail ("ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)", "lab2.c", 79, __extension__ __PRETTY_FUNCTION__));
        return ts_stop->tv_sec - ts_start->tv_sec +
                (ts_stop->tv_nsec - ts_start->tv_nsec) * 1E-9;
}

return_type: double

user_defined_types: struct timespec { long tv_sec; long tv_nsec; }


decompiled_code:
void *__fastcall call_test_impl(void *a1)
{
double v1; // xmm0_8
void *result; // rax
struct timespec v3; // [rsp+0h] [rbp-28h] BYREF
struct timespec tp; // [rsp+10h] [rbp-18h] BYREF

monotonic_time(&v3);
(*((void (__fastcall **)(_QWORD, _QWORD, int *))a1 + 2))(
*((unsigned int *)a1 + 2),
(unsigned int)iterations,
&shared_data);
monotonic_time(&tp);
v1 = time_diff(&v3.tv_sec, &tp.tv_sec);
result = 0LL;
*((double *)a1 + 3) = v1;
return result;
}

canonical_decompiled_code:
void *__fastcall func2(void *a1)
{
double v1; // xmm0_8
void *result; // rax
struct timespec v3; // [rsp+0h] [rbp-28h] BYREF
struct timespec tp; // [rsp+10h] [rbp-18h] BYREF

func0(&v3);
(*((void (__fastcall **)(_QWORD, _QWORD, int *))a1 + 2))(
*((unsigned int *)a1 + 2),
(unsigned int)iterations,
&shared_data);
func0(&tp);
v1 = func1(&v3.tv_sec, &tp.tv_sec);
result = 0LL;
*((double *)a1 + 3) = v1;
return result;
}

original_code:
void *
call_test_impl(void *_conf)
{
        thread_conf_t *conf = (thread_conf_t *)_conf;
        struct timespec ts_start, ts_stop;
        monotonic_time(&ts_start);
        conf->func(conf->thread_id, iterations, &shared_data);
        monotonic_time(&ts_stop);
        conf->run_time = time_diff(&ts_start, &ts_stop);
        return ((void *)0);
}

canonical_original_code:
void *call_test_impl(void *_conf)
{
        struct thread_conf_t *conf = (thread_conf_t *)_conf;
        struct timespec ts_start; struct timespec ts_stop;
        monotonic_time(&ts_start);
        conf->func(conf->thread_id, iterations, &shared_data);
        monotonic_time(&ts_stop);
        conf->run_time = time_diff(&ts_start, &ts_stop);
        return ((void *)0);
}

variable_types: struct thread_conf_t { unsigned long thread; int thread_id; void (*func)(int thread, int iterations, int *data); double run_time; } *


decompiled_code:
int __fastcall print_stats(__int64 a1)
{
int v1; // er12
double *v2; // rbx
unsigned int v3; // ebp
double v4; // xmm2_8
double v5; // xmm0_8
__int64 v6; // rsi

v1 = *((_DWORD *)test_impl + 4);
puts("Statistics:");
if ( v1 <= 0 )
{
v4 = 0.0;
}
else
{
v2 = (double *)(a1 + 24);
v3 = 0;
v4 = 0.0;
do
{
v5 = *v2;
v6 = v3++;
v2 += 4;
printf("\tThread %i: %.4f s (%.4e iterations/s)\n", v6, v5, (double)iterations / v5);
v4 = v4 + *(v2 - 4);
}
while ( v1 != v3 );
}
return printf(
"\tAverage execution time: %.4f s\n\tAvergage iterations/second: %.4e\n",
v4 / (double)v1,
(double)(v1 * iterations) / v4);
}

canonical_decompiled_code:
int __fastcall func3(__int64 a1)
{
int v1; // er12
double *v2; // rbx
unsigned int v3; // ebp
double v4; // xmm2_8
double v5; // xmm0_8
__int64 v6; // rsi

v1 = *((_DWORD *)test_impl + 4);
puts("Statistics:");
if ( v1 <= 0 )
{
v4 = 0.0;
}
else
{
v2 = (double *)(a1 + 24);
v3 = 0;
v4 = 0.0;
do
{
v5 = *v2;
v6 = v3++;
v2 += 4;
printf("\tThread %i: %.4f s (%.4e iterations/s)\n", v6, v5, (double)iterations / v5);
v4 = v4 + *(v2 - 4);
}
while ( v1 != v3 );
}
return printf(
"\tAverage execution time: %.4f s\n\tAvergage iterations/second: %.4e\n",
v4 / (double)v1,
(double)(v1 * iterations) / v4);
}

original_code:
static void
print_stats(thread_conf_t *threads)
{
        double run_time_sum = 0;
        int num_threads = test_impl->num_threads;
        printf("Statistics:\n");
        for (int i = 0; i < num_threads; i++) {
                thread_conf_t *t = &threads[i];
                printf("\tThread %i: %.4f s (%.4e iterations/s)\n",
                       i, t->run_time,
                       iterations / t->run_time);
                run_time_sum += t->run_time;
        }
        printf("\tAverage execution time: %.4f s\n"
               "\tAvergage iterations/second: %.4e\n",
               run_time_sum / num_threads,
               num_threads * iterations / run_time_sum);
}

canonical_original_code:
static void print_stats(struct thread_conf_t *threads)
{
        double run_time_sum = 0;
        int num_threads = test_impl->num_threads;
        printf("Statistics:\n");
        for (int i = 0; i < num_threads; i++) {
                struct thread_conf_t *t = &threads[i];
                printf("\tThread %i: %.4f s (%.4e iterations/s)\n",
                       i, t->run_time,
                       iterations / t->run_time);
                run_time_sum += t->run_time;
        }
        printf("\tAverage execution time: %.4f s\n"
               "\tAvergage iterations/second: %.4e\n",
               run_time_sum / num_threads,
               num_threads * iterations / run_time_sum);
}

variable_types: i int

user_defined_types: struct thread_conf_t { unsigned long thread; int thread_id; void (*func)(int thread, int iterations, int *data); double run_time; }


decompiled_code:
__int64 __fastcall set_cs_impl(char *s2)
{
const char **v1; // rbx
void **v2; // rbp
__int64 result; // rax
void **v4; // rbx
void *v5; // rax
const char *v6; // rdx
const char *v7; // rsi

if ( !strcmp("help", s2) )
{
v4 = &cs_impls;
puts("Critical section implementations:");
v5 = cs_impls;
if ( cs_impls )
{
do
{
while ( 1 )
{
v6 = (const char *)*((_QWORD *)v5 + 1);
v7 = *(const char **)v5;
if ( !v6 )
break;
++v4;
printf("\t%s - %s\n", v7, v6);
v5 = *v4;
if ( !*v4 )
goto LABEL_13;
}
++v4;
printf("\t%s\n", v7);
v5 = *v4;
}
while ( *v4 );
}
LABEL_13:
exit(0);
}
v1 = (const char **)cs_impls;
v2 = &cs_impls;
if ( cs_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = (const char **)v2[1];
++v2;
if ( !v1 )
goto LABEL_7;
}
cs_impl = v1;
result = 1LL;
}
else
{
LABEL_7:
fwrite(
"Invalid critical section implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x61uLL,
stderr);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(char *s2)
{
const char **v1; // rbx
void **v2; // rbp
__int64 result; // rax
void **v4; // rbx
void *v5; // rax
const char *v6; // rdx
const char *v7; // rsi

if ( !strcmp("help", s2) )
{
v4 = &cs_impls;
puts("Critical section implementations:");
v5 = cs_impls;
if ( cs_impls )
{
do
{
while ( 1 )
{
v6 = (const char *)*((_QWORD *)v5 + 1);
v7 = *(const char **)v5;
if ( !v6 )
break;
++v4;
printf("\t%s - %s\n", v7, v6);
v5 = *v4;
if ( !*v4 )
goto LABEL_13;
}
++v4;
printf("\t%s\n", v7);
v5 = *v4;
}
while ( *v4 );
}
LABEL_13:
exit(0);
}
v1 = (const char **)cs_impls;
v2 = &cs_impls;
if ( cs_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = (const char **)v2[1];
++v2;
if ( !v1 )
goto LABEL_7;
}
cs_impl = v1;
result = 1LL;
}
else
{
LABEL_7:
fwrite(
"Invalid critical section implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x61uLL,
stderr);
result = 0LL;
}
return result;
}

original_code:
static int
set_cs_impl(const char *name)
{
        if (!strcmp("help", name)) {
                printf("Critical section implementations:\n");
                for (critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                cs_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid critical section implementation specified, "
                        "use 'help' to list available implementations.\n");
                return 0;
        }
}

canonical_original_code:
static int set_cs_impl(char *name)
{
        if (!strcmp("help", name)) {
                printf("Critical section implementations:\n");
                for (struct critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (struct critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                cs_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid critical section implementation specified, "
                        "use 'help' to list available implementations.\n");
                return 0;
        }
}

variable_types:
name
char *

variable_types: struct critical_section_impl_t { char *name; char *desc; unsigned int max_threads; void (*init)(int num_threads); void (*fini)(); void (*enter)(int thread); void (*exit)(int thread); } **


decompiled_code:
__int64 __fastcall set_test_impl(char *s2)
{
const char **v1; // rbx
void **v2; // rbp
__int64 result; // rax
void **v4; // rbx
void *v5; // rax
const char *v6; // rdx
const char *v7; // rsi

if ( !strcmp("help", s2) )
{
v4 = &test_impls;
puts("Test implementations:");
v5 = test_impls;
if ( test_impls )
{
do
{
while ( 1 )
{
v6 = (const char *)*((_QWORD *)v5 + 1);
v7 = *(const char **)v5;
if ( !v6 )
break;
++v4;
printf("\t%s - %s\n", v7, v6);
v5 = *v4;
if ( !*v4 )
goto LABEL_13;
}
++v4;
printf("\t%s\n", v7);
v5 = *v4;
}
while ( *v4 );
}
LABEL_13:
exit(0);
}
v1 = (const char **)test_impls;
v2 = &test_impls;
if ( test_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = (const char **)v2[1];
++v2;
if ( !v1 )
goto LABEL_7;
}
test_impl = v1;
result = 1LL;
}
else
{
LABEL_7:
fwrite(
"Invalid test implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x55uLL,
stderr);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(char *s2)
{
const char **v1; // rbx
void **v2; // rbp
__int64 result; // rax
void **v4; // rbx
void *v5; // rax
const char *v6; // rdx
const char *v7; // rsi

if ( !strcmp("help", s2) )
{
v4 = &test_impls;
puts("Test implementations:");
v5 = test_impls;
if ( test_impls )
{
do
{
while ( 1 )
{
v6 = (const char *)*((_QWORD *)v5 + 1);
v7 = *(const char **)v5;
if ( !v6 )
break;
++v4;
printf("\t%s - %s\n", v7, v6);
v5 = *v4;
if ( !*v4 )
goto LABEL_13;
}
++v4;
printf("\t%s\n", v7);
v5 = *v4;
}
while ( *v4 );
}
LABEL_13:
exit(0);
}
v1 = (const char **)test_impls;
v2 = &test_impls;
if ( test_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = (const char **)v2[1];
++v2;
if ( !v1 )
goto LABEL_7;
}
test_impl = v1;
result = 1LL;
}
else
{
LABEL_7:
fwrite(
"Invalid test implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x55uLL,
stderr);
result = 0LL;
}
return result;
}

original_code:
static int
set_test_impl(const char *name)
{
        if (!strcmp("help", name)) {
                printf("Test implementations:\n");
                for (test_impl_t **impl = test_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (test_impl_t **impl = test_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                test_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid test implementation specified, use 'help' "
                        "to list available implementations.\n");
                return 0;
        }
}

canonical_original_code:
static int set_test_impl(char *name)
{
        if (!strcmp("help", name)) {
                printf("Test implementations:\n");
                for (struct test_impl_t **impl = test_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (struct test_impl_t **impl = test_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                test_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid test implementation specified, use 'help' "
                        "to list available implementations.\n");
                return 0;
        }
}

variable_types: struct test_impl_t { char *name; char *desc; int num_threads; void (*test[])(int thread, int iterations, int *data); } **


decompiled_code:
int start_threads()
{
_QWORD *v0; // r15
__int64 v1; // r13
pthread_t *v2; // rax
pthread_t *v3; // r14
pthread_t *v4; // r12
pthread_t *v5; // rbx
int v6; // ebp
pthread_t *v7; // r13
pthread_t v8; // rdi
int result; // eax

v0 = test_impl;
v1 = *((int *)test_impl + 4);
v2 = (pthread_t *)malloc(32 * v1);
if ( !v2 )
LABEL_12:
start_threads_cold();
v3 = v2;
if ( (int)v1 > 0 )
{
v4 = v2;
v5 = v2;
v6 = 0;
while ( 1 )
{
*((_DWORD *)v5 + 2) = v6;
v5[2] = v0[v6 + 3];
if ( pthread_create(v5, 0LL, call_test_impl, v5) )
goto LABEL_12;
++v6;
v5 += 4;
if ( (_DWORD)v1 == v6 )
break;
v0 = test_impl;
}
v7 = &v3[4 * (unsigned int)v1];
do
{
v8 = *v4;
v4 += 4;
pthread_join(v8, 0LL);
}
while ( v4 != v7 );
}
print_stats((__int64)v3);
putchar(10);
free(v3);
if ( shared_data )
result = printf(
"INCONSISTENCY after %d iterations - data = %d, but started at 0\n",
(unsigned int)iterations,
(unsigned int)shared_data);
else
result = printf("NO INCONSISTENCY after %d iterations\n", (unsigned int)iterations);
return result;
}

canonical_decompiled_code:
int func7()
{
_QWORD *v0; // r15
__int64 v1; // r13
pthread_t *v2; // rax
pthread_t *v3; // r14
pthread_t *v4; // r12
pthread_t *v5; // rbx
int v6; // ebp
pthread_t *v7; // r13
pthread_t v8; // rdi
int result; // eax

v0 = test_impl;
v1 = *((int *)test_impl + 4);
v2 = (pthread_t *)malloc(32 * v1);
if ( !v2 )
LABEL_12:
func8();
v3 = v2;
if ( (int)v1 > 0 )
{
v4 = v2;
v5 = v2;
v6 = 0;
while ( 1 )
{
*((_DWORD *)v5 + 2) = v6;
v5[2] = v0[v6 + 3];
if ( pthread_create(v5, 0LL, call_test_impl, v5) )
goto LABEL_12;
++v6;
v5 += 4;
if ( (_DWORD)v1 == v6 )
break;
v0 = test_impl;
}
v7 = &v3[4 * (unsigned int)v1];
do
{
v8 = *v4;
v4 += 4;
pthread_join(v8, 0LL);
}
while ( v4 != v7 );
}
func3((__int64)v3);
putchar(10);
free(v3);
if ( shared_data )
result = printf(
"INCONSISTENCY after %d iterations - data = %d, but started at 0\n",
(unsigned int)iterations,
(unsigned int)shared_data);
else
result = printf("NO INCONSISTENCY after %d iterations\n", (unsigned int)iterations);
return result;
}

original_code:
static void
start_threads()
{
        int num_threads = test_impl->num_threads;
        thread_conf_t *threads;
        if (!(threads = malloc(sizeof(*threads) * num_threads)))
                abort();
        for (int i = 0; i < num_threads; i++) {
                thread_conf_t *t = &threads[i];
                t->thread_id = i;
                t->func = test_impl->test[i];
                if (pthread_create(&t->thread, ((void *)0),
                                   &call_test_impl, t))
                        abort();
        }
        for (int i = 0; i < num_threads; i++)
                pthread_join(threads[i].thread, ((void *)0));
        print_stats(threads);
        printf("\n");
        free(threads);
        if (shared_data)
                printf("INCONSISTENCY after %d iterations - "
                       "data = %d, but started at 0\n",
                       iterations, shared_data);
        else
                printf("NO INCONSISTENCY after %d iterations\n",
                       iterations);
}

canonical_original_code:
static void start_threads()
{
        int num_threads = test_impl->num_threads;
        struct thread_conf_t *threads;
        if (!(threads = malloc(sizeof(*threads) * num_threads)))
                abort();
        for (int i = 0; i < num_threads; i++) {
                struct thread_conf_t *t = &threads[i];
                t->thread_id = i;
                t->func = test_impl->test[i];
                if (pthread_create(&t->thread, ((void *)0),
                                   &call_test_impl, t))
                        abort();
        }
        for (int i = 0; i < num_threads; i++)
                pthread_join(threads[i].thread, ((void *)0));
        print_stats(threads);
        printf("\n");
        free(threads);
        if (shared_data)
                printf("INCONSISTENCY after %d iterations - "
                       "data = %d, but started at 0\n",
                       iterations, shared_data);
        else
                printf("NO INCONSISTENCY after %d iterations\n",
                       iterations);
}