main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 *v3; // rcx
__int64 i; // rax
__int64 j; // rax
_QWORD *v6; // r12
__int64 v7; // r15
__int64 k; // rbx
__int64 v9; // rdi
unsigned __int16 v10; // ax
unsigned __int16 v11; // bp
unsigned __int16 v12; // bp
__int64 v13; // rax
__int64 v14; // r13
_QWORD *v15; // r14
_QWORD *v16; // r13
unsigned __int16 v17; // ax
unsigned __int16 v19; // [rsp+Ch] [rbp-17BCh]
__int16 v20; // [rsp+Eh] [rbp-17BAh]
unsigned __int16 *v21; // [rsp+10h] [rbp-17B8h]
__int64 v22; // [rsp+18h] [rbp-17B0h]
__int64 v23; // [rsp+20h] [rbp-17A8h]
__int64 v24; // [rsp+28h] [rbp-17A0h]
unsigned int v25; // [rsp+30h] [rbp-1798h]
unsigned int v26; // [rsp+34h] [rbp-1794h]
_QWORD *v27; // [rsp+38h] [rbp-1790h]
__int64 v28; // [rsp+40h] [rbp-1788h]
unsigned __int16 *ptr; // [rsp+48h] [rbp-1780h]
__int64 v30[4]; // [rsp+50h] [rbp-1778h] BYREF
char *v31; // [rsp+70h] [rbp-1758h] BYREF
char v32; // [rsp+86h] [rbp-1742h] BYREF
char v33; // [rsp+90h] [rbp-1738h] BYREF
char v34; // [rsp+640h] [rbp-1188h] BYREF
char v35; // [rsp+BF0h] [rbp-BD8h] BYREF
char v36; // [rsp+11A0h] [rbp-628h] BYREF
__int16 v37; // [rsp+174Ah] [rbp-7Eh] BYREF
char v38[4]; // [rsp+174Ch] [rbp-7Ch] BYREF
char v39[30]; // [rsp+1750h] [rbp-78h] BYREF
__int16 v40; // [rsp+176Eh] [rbp-5Ah] BYREF
__int16 v41; // [rsp+1770h] [rbp-58h] BYREF
unsigned __int16 v42; // [rsp+1772h] [rbp-56h] BYREF
unsigned __int16 v43; // [rsp+1774h] [rbp-54h] BYREF
unsigned __int16 v44; // [rsp+1776h] [rbp-52h] BYREF
unsigned __int16 v45; // [rsp+1778h] [rbp-50h] BYREF
unsigned __int16 v46; // [rsp+177Ah] [rbp-4Eh] BYREF
unsigned __int16 v47; // [rsp+177Ch] [rbp-4Ch] BYREF
unsigned __int16 v48; // [rsp+177Eh] [rbp-4Ah] BYREF
unsigned __int16 v49; // [rsp+1780h] [rbp-48h] BYREF
unsigned __int16 v50; // [rsp+1782h] [rbp-46h] BYREF
unsigned int v51; // [rsp+1784h] [rbp-44h] BYREF
unsigned int v52; // [rsp+1788h] [rbp-40h] BYREF
unsigned int v53[15]; // [rsp+178Ch] [rbp-3Ch] BYREF

v23 = ui16colorim(0LL, 479LL, 0LL, 719LL);
v24 = ui16colorim(0LL, 479LL, 0LL, 719LL);
printf("Image pipeline version %f\n", *(double *)&LC2);
print_config();
ptr = (unsigned __int16 *)malloc(0x10uLL);
readPGM("inputGRBG10bitg2p2.pgm", ptr);
v27 = (_QWORD *)*((_QWORD *)ptr + 1);
v30[0] = (__int64)&v36;
v30[1] = (__int64)&v35;
v30[2] = (__int64)&v34;
v30[3] = (__int64)&v33;
v31 = &v32;
v28 = ui16vector(0LL, *ptr - 1);
v22 = ui16vector(0LL, ptr[1] - 1);
construct_lens_profile(0LL, v28, v22);
v50 = 32;
v49 = 32;
v48 = 32;
choosematrix(v39, 32LL, 32LL);
v46 = 8;
v47 = 1;
v37 = 1;
v51 = 0;
v52 = 0;
v53[0] = 0;
v3 = v30;
do
{
for ( i = 0LL; i != 1448; i += 2LL )
*(_WORD *)(*v3 + i) = 0;
++v3;
}
while ( v3 != (__int64 *)&v31 );
for ( j = 0LL; j != 10; j += 2LL )
*(_WORD *)&v31[j] = 0;
v6 = v27;
v21 = (unsigned __int16 *)v28;
v20 = -181;
v19 = -4;
v7 = 0LL;
v26 = 0;
v25 = 0;
while ( 2 )
{
v14 = 8LL * v19;
v15 = (_QWORD *)(v24 + v14);
v16 = (_QWORD *)(v23 + v14);
for ( k = 0LL; ; ++k )
{
v9 = (unsigned __int16)black_level_subtract(*(unsigned __int16 *)(*v6 + 2 * k), 1LL);
v10 = lens_shading_correction(v9, *v21, *(unsigned __int16 *)(v22 + 2 * k));
v11 = awb_sums_and_cga(v10, (unsigned int)v7, (unsigned int)k, v50, v49, v48, v53, &v52, &v51);
update_buffer(v11, v30);
if ( (unsigned __int16)v7 <= 3u )
{
v43 = v11;
v44 = v11;
v45 = v11;
}
else
{
colorinterpolate_noisereduce(v30, v19, (unsigned int)k, 34LL, &v45, &v44, &v43);
}
colorcorrect(v39, &v45, &v44, &v43);
v45 = gammacorrect_LUT(v45);
v44 = gammacorrect_LUT(v44);
v43 = gammacorrect_LUT(v43);
v12 = v42;
rgb2yuv(v45, v44, v43, &v42, &v41, &v40);
v25 += (unsigned __int16)absdiff16(v12, v42);
if ( (unsigned __int16)v20 > 0x166u || (unsigned __int16)(k - 181) > 0x166u )
break;
v26 += (unsigned __int16)absdiff16(v12, v42);
LABEL_18:
v13 = (unsigned __int16)(k - 2);
**(_WORD **)(*v15 + 8 * v13) = v45;
*(_WORD *)(*(_QWORD *)(*v15 + 8 * v13) + 2LL) = v44;
*(_WORD *)(*(_QWORD *)(*v15 + 8 * v13) + 4LL) = v43;
**(_WORD **)(*v16 + 8 * v13) = v42;
*(_WORD *)(*(_QWORD *)(*v16 + 8 * v13) + 2LL) = v41;
*(_WORD *)(*(_QWORD *)(*v16 + 8 * v13) + 4LL) = v40;
LABEL_12:
;
}
if ( (unsigned __int16)(k - 2) <= 0x2CFu && (unsigned __int16)v7 > 3u )
goto LABEL_18;
if ( (unsigned __int16)(k + 1) <= 0x2D3u )
goto LABEL_12;
++v7;
++v19;
++v20;
++v6;
++v21;
if ( v7 != 484 )
continue;
break;
}
awb(v53[0], v52, v51, &v50, &v49, &v48);
printf("awb output: R=%d, G=%d, B=%d\n", v50, v49, v48);
choosematrix(v39, v50, v48);
autoexposure(v53[0], v52, v51, &v47, &v46);
printf("ae output: Texp=%d Gain=%d\n", v46, v47);
v17 = autofocus(16LL, v26, v38, &v37, 1LL);
printf("af output: E=%d EW=%d and focus setting %d\n", v25, v26, v17);
puts("Output in RGB 444 format");
writeppm("output.ppm", v24);
free_ui16vector(v28, 0LL, 483LL);
free_ui16vector(v22, 0LL, 723LL);
free_ui16colorim(v23, 0LL, 479LL, 0LL, 719LL);
free_ui16colorim(v24, 0LL, 479LL, 0LL, 719LL);
free_ui16matrix(v27, 0LL, 479LL, 0LL, 719LL);
free(ptr);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 *v3; // rcx
__int64 i; // rax
__int64 j; // rax
_QWORD *v6; // r12
__int64 v7; // r15
__int64 k; // rbx
__int64 v9; // rdi
unsigned __int16 v10; // ax
unsigned __int16 v11; // bp
unsigned __int16 v12; // bp
__int64 v13; // rax
__int64 v14; // r13
_QWORD *v15; // r14
_QWORD *v16; // r13
unsigned __int16 v17; // ax
unsigned __int16 v19; // [rsp+Ch] [rbp-17BCh]
__int16 v20; // [rsp+Eh] [rbp-17BAh]
unsigned __int16 *v21; // [rsp+10h] [rbp-17B8h]
__int64 v22; // [rsp+18h] [rbp-17B0h]
__int64 v23; // [rsp+20h] [rbp-17A8h]
__int64 v24; // [rsp+28h] [rbp-17A0h]
unsigned int v25; // [rsp+30h] [rbp-1798h]
unsigned int v26; // [rsp+34h] [rbp-1794h]
_QWORD *v27; // [rsp+38h] [rbp-1790h]
__int64 v28; // [rsp+40h] [rbp-1788h]
unsigned __int16 *ptr; // [rsp+48h] [rbp-1780h]
__int64 v30[4]; // [rsp+50h] [rbp-1778h] BYREF
char *v31; // [rsp+70h] [rbp-1758h] BYREF
char v32; // [rsp+86h] [rbp-1742h] BYREF
char v33; // [rsp+90h] [rbp-1738h] BYREF
char v34; // [rsp+640h] [rbp-1188h] BYREF
char v35; // [rsp+BF0h] [rbp-BD8h] BYREF
char v36; // [rsp+11A0h] [rbp-628h] BYREF
__int16 v37; // [rsp+174Ah] [rbp-7Eh] BYREF
char v38[4]; // [rsp+174Ch] [rbp-7Ch] BYREF
char v39[30]; // [rsp+1750h] [rbp-78h] BYREF
__int16 v40; // [rsp+176Eh] [rbp-5Ah] BYREF
__int16 v41; // [rsp+1770h] [rbp-58h] BYREF
unsigned __int16 v42; // [rsp+1772h] [rbp-56h] BYREF
unsigned __int16 v43; // [rsp+1774h] [rbp-54h] BYREF
unsigned __int16 v44; // [rsp+1776h] [rbp-52h] BYREF
unsigned __int16 v45; // [rsp+1778h] [rbp-50h] BYREF
unsigned __int16 v46; // [rsp+177Ah] [rbp-4Eh] BYREF
unsigned __int16 v47; // [rsp+177Ch] [rbp-4Ch] BYREF
unsigned __int16 v48; // [rsp+177Eh] [rbp-4Ah] BYREF
unsigned __int16 v49; // [rsp+1780h] [rbp-48h] BYREF
unsigned __int16 v50; // [rsp+1782h] [rbp-46h] BYREF
unsigned int v51; // [rsp+1784h] [rbp-44h] BYREF
unsigned int v52; // [rsp+1788h] [rbp-40h] BYREF
unsigned int v53[15]; // [rsp+178Ch] [rbp-3Ch] BYREF

v23 = ui16colorim(0LL, 479LL, 0LL, 719LL);
v24 = ui16colorim(0LL, 479LL, 0LL, 719LL);
printf("Image pipeline version %f\n", *(double *)&LC2);
func0();
ptr = (unsigned __int16 *)malloc(0x10uLL);
readPGM("inputGRBG10bitg2p2.pgm", ptr);
v27 = (_QWORD *)*((_QWORD *)ptr + 1);
v30[0] = (__int64)&v36;
v30[1] = (__int64)&v35;
v30[2] = (__int64)&v34;
v30[3] = (__int64)&v33;
v31 = &v32;
v28 = ui16vector(0LL, *ptr - 1);
v22 = ui16vector(0LL, ptr[1] - 1);
construct_lens_profile(0LL, v28, v22);
v50 = 32;
v49 = 32;
v48 = 32;
choosematrix(v39, 32LL, 32LL);
v46 = 8;
v47 = 1;
v37 = 1;
v51 = 0;
v52 = 0;
v53[0] = 0;
v3 = v30;
do
{
for ( i = 0LL; i != 1448; i += 2LL )
*(_WORD *)(*v3 + i) = 0;
++v3;
}
while ( v3 != (__int64 *)&v31 );
for ( j = 0LL; j != 10; j += 2LL )
*(_WORD *)&v31[j] = 0;
v6 = v27;
v21 = (unsigned __int16 *)v28;
v20 = -181;
v19 = -4;
v7 = 0LL;
v26 = 0;
v25 = 0;
while ( 2 )
{
v14 = 8LL * v19;
v15 = (_QWORD *)(v24 + v14);
v16 = (_QWORD *)(v23 + v14);
for ( k = 0LL; ; ++k )
{
v9 = (unsigned __int16)black_level_subtract(*(unsigned __int16 *)(*v6 + 2 * k), 1LL);
v10 = lens_shading_correction(v9, *v21, *(unsigned __int16 *)(v22 + 2 * k));
v11 = awb_sums_and_cga(v10, (unsigned int)v7, (unsigned int)k, v50, v49, v48, v53, &v52, &v51);
update_buffer(v11, v30);
if ( (unsigned __int16)v7 <= 3u )
{
v43 = v11;
v44 = v11;
v45 = v11;
}
else
{
colorinterpolate_noisereduce(v30, v19, (unsigned int)k, 34LL, &v45, &v44, &v43);
}
colorcorrect(v39, &v45, &v44, &v43);
v45 = gammacorrect_LUT(v45);
v44 = gammacorrect_LUT(v44);
v43 = gammacorrect_LUT(v43);
v12 = v42;
rgb2yuv(v45, v44, v43, &v42, &v41, &v40);
v25 += (unsigned __int16)absdiff16(v12, v42);
if ( (unsigned __int16)v20 > 0x166u || (unsigned __int16)(k - 181) > 0x166u )
break;
v26 += (unsigned __int16)absdiff16(v12, v42);
LABEL_18:
v13 = (unsigned __int16)(k - 2);
**(_WORD **)(*v15 + 8 * v13) = v45;
*(_WORD *)(*(_QWORD *)(*v15 + 8 * v13) + 2LL) = v44;
*(_WORD *)(*(_QWORD *)(*v15 + 8 * v13) + 4LL) = v43;
**(_WORD **)(*v16 + 8 * v13) = v42;
*(_WORD *)(*(_QWORD *)(*v16 + 8 * v13) + 2LL) = v41;
*(_WORD *)(*(_QWORD *)(*v16 + 8 * v13) + 4LL) = v40;
LABEL_12:
;
}
if ( (unsigned __int16)(k - 2) <= 0x2CFu && (unsigned __int16)v7 > 3u )
goto LABEL_18;
if ( (unsigned __int16)(k + 1) <= 0x2D3u )
goto LABEL_12;
++v7;
++v19;
++v20;
++v6;
++v21;
if ( v7 != 484 )
continue;
break;
}
awb(v53[0], v52, v51, &v50, &v49, &v48);
printf("awb output: R=%d, G=%d, B=%d\n", v50, v49, v48);
choosematrix(v39, v50, v48);
autoexposure(v53[0], v52, v51, &v47, &v46);
printf("ae output: Texp=%d Gain=%d\n", v46, v47);
v17 = autofocus(16LL, v26, v38, &v37, 1LL);
printf("af output: E=%d EW=%d and focus setting %d\n", v25, v26, v17);
puts("Output in RGB 444 format");
writeppm("output.ppm", v24);
free_ui16vector(v28, 0LL, 483LL);
free_ui16vector(v22, 0LL, 723LL);
free_ui16colorim(v23, 0LL, 479LL, 0LL, 719LL);
free_ui16colorim(v24, 0LL, 479LL, 0LL, 719LL);
free_ui16matrix(v27, 0LL, 479LL, 0LL, 719LL);
free(ptr);
return 0;
}

original_code:
int main ()
{
    uint16_t **I,**Irgb565,***Ic,***Iyuv,***Iycc, ***Ibtu;
    PGMData *inputpgm, *outputpgm;
    uint16_t noise_threshold;
    uint32_t rsum,gsum,bsum;
    uint16_t awb_R,awb_G,awb_B;
    uint16_t Gain,Texp;
    uint16_t *row_prf, *col_prf;
    uint16_t r,c;
    uint16_t r2,c2;
    uint16_t pixel;
    uint16_t red,green,blue;
    uint16_t y,u,v,prevy;
    int16_t ccm[3][3];
    uint32_t edginess;
    uint32_t edginess_window;
    uint32_t prev_edginess;
    uint32_t focus;
    uint16_t focus_stepsize;
    int16_t focus_direction;
    uint16_t field = 0;
    InputFormat input = PIXELARRAY;
    OutputFormat output = RGB444;
    Iyuv = ui16colorim(0,480 -1,0,720 -1);
    Ic = ui16colorim(0,480 -1,0,720 -1);
    printf("Image pipeline version %f\n",0.5);
    print_config();
    inputpgm = (PGMData *)malloc(sizeof(PGMData));
    if (input != TESTPATTERN)
    {
        readPGM("inputGRBG10bitg2p2.pgm",inputpgm);
        I = inputpgm->matrix;
    }
 uint16_t row1[724],row2[724],row3[724],row4[724],row5[5] ;
 uint16_t *buffer[5] = {row1,row2,row3,row4,row5};
    row_prf = ui16vector(0,inputpgm->height-1);
    col_prf = ui16vector(0,inputpgm->width-1);
    construct_lens_profile(0, row_prf, col_prf);
    awb_R = 1<<5; awb_G = 1<<5; awb_B = 1<<5;
    choosematrix(ccm,awb_R,awb_B);
    Texp = 8;
    Gain = 1;
    focus_direction = 1;
 focus = 16;
 focus_stepsize = 1;
    rsum = gsum = bsum = 0;
    noise_threshold = 33 - Gain + (Texp>>2);
    if (noise_threshold < 16)
        noise_threshold = 16;
    for (r=0; r<5 -1;r++)
        for (c=0; c<724; c++)
            buffer[r][c] = 0;
  for (c=0; c<5; c++)
            buffer[4][c] = 0;
    edginess = 0;
    edginess_window = 0;
    for (r=0; r<484; r++)
    {
        for (c=0; c<724; c++)
        {
            if (input == TESTPATTERN)
                pixel = test_pattern_generator();
            else
                pixel = I[r][c];
            pixel = black_level_subtract(pixel,1);
            pixel = lens_shading_correction(pixel, row_prf[r], col_prf[c]);
            pixel = awb_sums_and_cga(pixel, r, c, awb_R, awb_G, awb_B, &rsum, &gsum, &bsum);
            update_buffer(pixel, buffer);
            if (r >= (5 - 1))
            {
                colorinterpolate_noisereduce(buffer,r-(5 - 1),c,noise_threshold,&red,&green,&blue);
            } else {
                red = green = blue = pixel;
            }
            colorcorrect(ccm,&red,&green,&blue);
            red = gammacorrect_LUT(red);
   green = gammacorrect_LUT(green);
            blue = gammacorrect_LUT(blue);
            prevy = y;
            rgb2yuv(red,green,blue,&y,&u,&v);
            edginess = edginess + absdiff16(prevy,y);
            if (r > 180 && r < 540 && c > 180 && c < 540)
                edginess_window = edginess_window + absdiff16(prevy,y);
            if (r>= (5 - 1) && c > 1 && c < 724 -2)
            {
             r2 = r-(5 - 1); c2 = c-2;
                Ic[r2][c2][0] = red; Ic[r2][c2][1] = green; Ic[r2][c2][2] = blue;
                Iyuv[r2][c2][0] = y; Iyuv[r2][c2][1] = u; Iyuv[r2][c2][2] = v;
            }
        }
    }
    awb(rsum,gsum,bsum,&awb_R,&awb_G,&awb_B);
    printf("awb output: R=%d, G=%d, B=%d\n",awb_R,awb_G,awb_B);
    choosematrix(ccm,awb_R,awb_B);
    autoexposure(rsum,gsum,bsum,&Gain,&Texp);
    printf("ae output: Texp=%d Gain=%d\n",Texp,Gain);
    focus=autofocus(focus, edginess_window, &prev_edginess, &focus_direction, focus_stepsize);
    printf("af output: E=%d EW=%d and focus setting %d\n",edginess,edginess_window,focus);
    switch (output) {
        case YUV444:
            printf("Output in YUV 444 format\n");
            writeppm("outputyuv.ppm",Iyuv);
            break;
        case YCbCr422:
            printf("Output in YCbCr 422 format\n");
            Iycc = ui16colorim(0,480 -1,0,720 -1);
            rgb2ycbcr422(Ic,Iycc);
            writeppm("outputycbcr422.ppm",Iycc);
            free_ui16colorim(Iycc,0,480 -1,0,720 -1);
            break;
        case RGB565:
            printf("Output in RGB 565 format\n");
            Irgb565 = ui16matrix(0,480 -1,0,720 -1);
            rgb2rgb565(Ic,Irgb565);
            inputpgm->matrix = Irgb565;
            outputpgm = inputpgm;
            writePGM("outputrgb565.ppm",outputpgm);
            free_ui16matrix(Irgb565,0,480 -1,0,720 -1);
            break;
        case ITUBT656:
            printf("Output in ITU BT 565 format\n");
            Ibtu = ui16colorim(0,480 -1,0,720 -1);
            rgb2ycbcr422(Ic,Ibtu);
            writebtu656("outputbtu",Ibtu,field);
            free_ui16colorim(Ibtu,0,480 -1,0,720 -1);
            if (field == 0)
                field = 1;
            else
                field = 0;
            break;
        case RGB444:
        default:
            printf("Output in RGB 444 format\n");
            writeppm("output.ppm",Ic);
    }
    free_ui16vector(row_prf,0,484 -1);
    free_ui16vector(col_prf,0,724 -1);
    free_ui16colorim(Iyuv,0,480 -1,0,720 -1);
    free_ui16colorim(Ic,0,480 -1,0,720 -1);
    free_ui16matrix(I,0,480 -1,0,720 -1);
    free(inputpgm);
    return 0;
}

canonical_original_code:
int main()
{
    unsigned short **I; unsigned short **Irgb565; unsigned short ***Ic; unsigned short ***Iyuv; unsigned short ***Iycc; unsigned short ***Ibtu;
    struct _PGMData *inputpgm; struct _PGMData *outputpgm;
    unsigned short noise_threshold;
    unsigned int rsum; unsigned int gsum; unsigned int bsum;
    unsigned short awb_R; unsigned short awb_G; unsigned short awb_B;
    unsigned short Gain; unsigned short Texp;
    unsigned short *row_prf; unsigned short *col_prf;
    unsigned short r; unsigned short c;
    unsigned short r2; unsigned short c2;
    unsigned short pixel;
    unsigned short red; unsigned short green; unsigned short blue;
    unsigned short y; unsigned short u; unsigned short v; unsigned short prevy;
    short ccm[3][3];
    unsigned int edginess;
    unsigned int edginess_window;
    unsigned int prev_edginess;
    unsigned int focus;
    unsigned short focus_stepsize;
    short focus_direction;
    unsigned short field = 0;
    enum _InputFormat input = PIXELARRAY;
    enum _OutputFormat output = RGB444;
    Iyuv = ui16colorim(0,480 -1,0,720 -1);
    Ic = ui16colorim(0,480 -1,0,720 -1);
    printf("Image pipeline version %f\n",0.5);
    print_config();
    inputpgm = (struct _PGMData *)malloc(sizeof(PGMData));
    if (input != TESTPATTERN)
    {
        readPGM("inputGRBG10bitg2p2.pgm",inputpgm);
        I = inputpgm->matrix;
    }
 unsigned short row1[724]; unsigned short row2[724]; unsigned short row3[724]; unsigned short row4[724]; unsigned short row5[5];
 unsigned short *buffer[5] = {row1,row2,row3,row4,row5};
    row_prf = ui16vector(0,inputpgm->height-1);
    col_prf = ui16vector(0,inputpgm->width-1);
    construct_lens_profile(0, row_prf, col_prf);
    awb_R = 1<<5; awb_G = 1<<5; awb_B = 1<<5;
    choosematrix(ccm,awb_R,awb_B);
    Texp = 8;
    Gain = 1;
    focus_direction = 1;
 focus = 16;
 focus_stepsize = 1;
    rsum = gsum = bsum = 0;
    noise_threshold = 33 - Gain + (Texp>>2);
    if (noise_threshold < 16)
        noise_threshold = 16;
    for (r=0; r<5 -1;r++)
        for (c=0; c<724; c++)
            buffer[r][c] = 0;
  for (c=0; c<5; c++)
            buffer[4][c] = 0;
    edginess = 0;
    edginess_window = 0;
    for (r=0; r<484; r++)
    {
        for (c=0; c<724; c++)
        {
            if (input == TESTPATTERN)
                pixel = test_pattern_generator();
            else
                pixel = I[r][c];
            pixel = black_level_subtract(pixel,1);
            pixel = lens_shading_correction(pixel, row_prf[r], col_prf[c]);
            pixel = awb_sums_and_cga(pixel, r, c, awb_R, awb_G, awb_B, &rsum, &gsum, &bsum);
            update_buffer(pixel, buffer);
            if (r >= (5 - 1))
            {
                colorinterpolate_noisereduce(buffer,r-(5 - 1),c,noise_threshold,&red,&green,&blue);
            } else {
                red = green = blue = pixel;
            }
            colorcorrect(ccm,&red,&green,&blue);
            red = gammacorrect_LUT(red);
   green = gammacorrect_LUT(green);
            blue = gammacorrect_LUT(blue);
            prevy = y;
            rgb2yuv(red,green,blue,&y,&u,&v);
            edginess = edginess + absdiff16(prevy,y);
            if (r > 180 && r < 540 && c > 180 && c < 540)
                edginess_window = edginess_window + absdiff16(prevy,y);
            if (r>= (5 - 1) && c > 1 && c < 724 -2)
            {
             r2 = r-(5 - 1); c2 = c-2;
                Ic[r2][c2][0] = red; Ic[r2][c2][1] = green; Ic[r2][c2][2] = blue;
                Iyuv[r2][c2][0] = y; Iyuv[r2][c2][1] = u; Iyuv[r2][c2][2] = v;
            }
        }
    }
    awb(rsum,gsum,bsum,&awb_R,&awb_G,&awb_B);
    printf("awb output: R=%d, G=%d, B=%d\n",awb_R,awb_G,awb_B);
    choosematrix(ccm,awb_R,awb_B);
    autoexposure(rsum,gsum,bsum,&Gain,&Texp);
    printf("ae output: Texp=%d Gain=%d\n",Texp,Gain);
    focus=autofocus(focus, edginess_window, &prev_edginess, &focus_direction, focus_stepsize);
    printf("af output: E=%d EW=%d and focus setting %d\n",edginess,edginess_window,focus);
    switch (output) {
        case YUV444:
            printf("Output in YUV 444 format\n");
            writeppm("outputyuv.ppm",Iyuv);
            break;
        case YCbCr422:
            printf("Output in YCbCr 422 format\n");
            Iycc = ui16colorim(0,480 -1,0,720 -1);
            rgb2ycbcr422(Ic,Iycc);
            writeppm("outputycbcr422.ppm",Iycc);
            free_ui16colorim(Iycc,0,480 -1,0,720 -1);
            break;
        case RGB565:
            printf("Output in RGB 565 format\n");
            Irgb565 = ui16matrix(0,480 -1,0,720 -1);
            rgb2rgb565(Ic,Irgb565);
            inputpgm->matrix = Irgb565;
            outputpgm = inputpgm;
            writePGM("outputrgb565.ppm",outputpgm);
            free_ui16matrix(Irgb565,0,480 -1,0,720 -1);
            break;
        case ITUBT656:
            printf("Output in ITU BT 565 format\n");
            Ibtu = ui16colorim(0,480 -1,0,720 -1);
            rgb2ycbcr422(Ic,Ibtu);
            writebtu656("outputbtu",Ibtu,field);
            free_ui16colorim(Ibtu,0,480 -1,0,720 -1);
            if (field == 0)
                field = 1;
            else
                field = 0;
            break;
        case RGB444:
        default:
            printf("Output in RGB 444 format\n");
            writeppm("output.ppm",Ic);
    }
    free_ui16vector(row_prf,0,484 -1);
    free_ui16vector(col_prf,0,724 -1);
    free_ui16colorim(Iyuv,0,480 -1,0,720 -1);
    free_ui16colorim(Ic,0,480 -1,0,720 -1);
    free_ui16matrix(I,0,480 -1,0,720 -1);
    free(inputpgm);
    return 0;
}

variable_types:
I
unsigned short **

variable_types:
Ic
unsigned short ***

variable_types:
Iyuv
unsigned short ***

variable_types:
Iycc
unsigned short ***

variable_types:
Ibtu
unsigned short ***

variable_types: struct _PGMData { unsigned short height; unsigned short width; unsigned short max_gray; unsigned short **matrix; } *

variable_types:
rsum
unsigned int

variable_types:
gsum
unsigned int

variable_types:
bsum
unsigned int

variable_types:
Gain
unsigned short

variable_types:
Texp
unsigned short

variable_types:
r
unsigned short

variable_types:
c
unsigned short

variable_types:
pixel
unsigned short

variable_types:
red
unsigned short

variable_types:
green
unsigned short

variable_types:
blue
unsigned short

variable_types:
y
unsigned short

variable_types:
u
unsigned short

variable_types:
v
unsigned short

variable_types:
prevy
unsigned short

variable_types:
ccm
short [3][3]

variable_types:
edginess
unsigned int

variable_types:
focus
unsigned int

variable_types:
field
unsigned short

variable_types: enum _InputFormat { TESTPATTERN=0, PIXELARRAY=1 }

variable_types: enum _OutputFormat { YUV444=0, YCbCr422=1, RGB565=2, RGB444=3, ITUBT656=4 }

variable_types:
buffer
unsigned short *[5]


choosematrix

canonical_original_code:
void choosematrix(short ccm[3][3], unsigned short awb_R, unsigned short awb_B)
{
    unsigned short dist; unsigned short min_dist; unsigned short illum_ndx;
    min_dist = 1<<15;
    dist = absdiff16(32,awb_B) +
               absdiff16(32,awb_R);
    if (dist < min_dist) {
        illum_ndx = 0;
  min_dist = dist;
 }
 dist = absdiff16(40,awb_B) +
               absdiff16(24,awb_R);
 if (dist < min_dist) {
  illum_ndx = 1;
  min_dist = dist;
 }
 dist = absdiff16(24,awb_B) +
               absdiff16(40,awb_R);
 if (dist < min_dist) {
  illum_ndx = 2;
  min_dist = dist;
 }
 dist = absdiff16(28,awb_B) +
               absdiff16(36,awb_R);
 if (dist < min_dist) {
  illum_ndx = 3;
  min_dist = dist;
 }
 switch (illum_ndx) {
  case 0:
        ccm[0][0] = 32; ccm[0][1] = 0; ccm[0][2] = 0;
        ccm[1][0] = 0; ccm[1][1] = 32; ccm[1][2] = 0;
        ccm[2][0] = 0; ccm[2][1] = 0; ccm[2][2] = 32;
  break;
  case 1:
     ccm[0][0] = 32; ccm[0][1] = 0; ccm[0][2] = 0;
        ccm[1][0] = 0; ccm[1][1] = 32; ccm[1][2] = 0;
        ccm[2][0] = 0; ccm[2][1] = 0; ccm[2][2] = 32;
  break;
  case 2:
     ccm[0][0] = 32; ccm[0][1] = 0; ccm[0][2] = 0;
        ccm[1][0] = 0; ccm[1][1] = 32; ccm[1][2] = 0;
        ccm[2][0] = 0; ccm[2][1] = 0; ccm[2][2] = 32;
  break;
  case 3:
  ccm[0][0] = 32; ccm[0][1] = 0; ccm[0][2] = 0;
        ccm[1][0] = 0; ccm[1][1] = 32; ccm[1][2] = 0;
        ccm[2][0] = 0; ccm[2][1] = 0; ccm[2][2] = 32;
  break;
    }
   printf("Illuminant #%d chosen\n",illum_ndx);
}

variable_types:
dist
unsigned short

return_type: void


colorcorrect

original_code:
void colorcorrect(int16_t ccm[3][3], uint16_t *red, uint16_t *green, uint16_t *blue)
{
    uint16_t localred,localgreen,localblue;
    int32_t sum;
    uint32_t temp;
 localred = *red; localgreen = *green; localblue = *blue;
 sum = ccm[0][0]*localred + ccm[0][1]*localgreen + ccm[0][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *red = temp;
 sum = ccm[1][0]*localred + ccm[1][1]*localgreen + ccm[1][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *green = temp;
 sum = ccm[2][0]*localred + ccm[2][1]*localgreen + ccm[2][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *blue = temp;
}

canonical_original_code:
void colorcorrect(short ccm[3][3], unsigned short *red, unsigned short *green, unsigned short *blue)
{
    unsigned short localred; unsigned short localgreen; unsigned short localblue;
    int sum;
    unsigned int temp;
 localred = *red; localgreen = *green; localblue = *blue;
 sum = ccm[0][0]*localred + ccm[0][1]*localgreen + ccm[0][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *red = temp;
 sum = ccm[1][0]*localred + ccm[1][1]*localgreen + ccm[1][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *green = temp;
 sum = ccm[2][0]*localred + ccm[2][1]*localgreen + ccm[2][2]*localblue;
 if (sum<0)
  sum = 0;
    temp = sum >> 5;
    if (temp > ((1<<10)-1))
        temp = ((1<<10)-1);
 *blue = temp;
}

variable_types:
red
unsigned short *

variable_types:
green
unsigned short *

variable_types:
blue
unsigned short *

variable_types:
localred
unsigned short

variable_types:
localgreen
unsigned short

variable_types:
localblue
unsigned short

variable_types: sum int

variable_types:
temp
unsigned int


iperror

decompiled_code:
void __fastcall __noreturn iperror(const char *a1)
{
fwrite("Ipipe run-time error...\n", 1uLL, 0x18uLL, stderr);
fprintf(stderr, "%s\n", a1);
fwrite("...now exiting to system...\n", 1uLL, 0x1CuLL, stderr);
exit(1);
}

canonical_decompiled_code:
void __fastcall __noreturn func0(const char *a1)
{
fwrite("Ipipe run-time error...\n", 1uLL, 0x18uLL, stderr);
fprintf(stderr, "%s\n", a1);
fwrite("...now exiting to system...\n", 1uLL, 0x1CuLL, stderr);
exit(1);
}

original_code:
void iperror(char error_text[])
{
 fprintf(stderr,"Ipipe run-time error...\n");
 fprintf(stderr,"%s\n",error_text);
 fprintf(stderr,"...now exiting to system...\n");
 exit(1);
}


decompiled_code:
char *__fastcall ui16vector(__int64 a1, __int64 a2)
{
char *v2; // rax

v2 = (char *)malloc(2 * (a2 - a1) + 4);
if ( !v2 )
iperror("allocation failure in ui16vector()");
return &v2[2 * (1 - a1)];
}

canonical_decompiled_code:
char *__fastcall func1(__int64 a1, __int64 a2)
{
char *v2; // rax

v2 = (char *)malloc(2 * (a2 - a1) + 4);
if ( !v2 )
func0("allocation failure in ui16vector()");
return &v2[2 * (1 - a1)];
}

original_code:
unsigned short *ui16vector(long nl, long nh)
{
 unsigned short *v;
 v=(unsigned short *)malloc((size_t) ((nh-nl+1+1)*sizeof(unsigned short)));
 if (!v) iperror("allocation failure in ui16vector()");
 return v-nl+1;
}

canonical_original_code:
unsigned short *ui16vector(long nl, long nh)
{
 unsigned short *v;
 v=(unsigned short *)malloc((unsigned long) ((nh-nl+1+1)*sizeof(unsigned short)));
 if (!v) iperror("allocation failure in ui16vector()");
 return v-nl+1;
}

variable_types: nl long

variable_types: nh long

variable_types:
v
unsigned short *

return_type: unsigned short *


original_code:
unsigned short **ui16matrix(long nrl, long nrh, long ncl, long nch)
{
 long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
 unsigned short **m;
 m=(unsigned short **) malloc((size_t)((nrow+1)*sizeof(unsigned short *)));
 if (!m) iperror("allocation failure 1 in matrix()");
 m += 1;
 m -= nrl;
 m[nrl]=(unsigned short *) malloc((size_t)((nrow*ncol+1)*sizeof(unsigned short)));
 if (!m[nrl]) iperror("allocation failure 2 in matrix()");
 m[nrl] += 1;
 m[nrl] -= ncl;
 for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
 return m;
}

canonical_original_code:
unsigned short **ui16matrix(long nrl, long nrh, long ncl, long nch)
{
 long i; long nrow = nrh-nrl+1; long ncol = nch-ncl+1;
 unsigned short **m;
 m=(unsigned short **) malloc((unsigned long)((nrow+1)*sizeof(unsigned short *)));
 if (!m) iperror("allocation failure 1 in matrix()");
 m += 1;
 m -= nrl;
 m[nrl]=(unsigned short *) malloc((unsigned long)((nrow*ncol+1)*sizeof(unsigned short)));
 if (!m[nrl]) iperror("allocation failure 2 in matrix()");
 m[nrl] += 1;
 m[nrl] -= ncl;
 for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
 return m;
}

variable_types: nrl long

variable_types: nrh long

variable_types: ncl long

variable_types: nch long

variable_types: i long

variable_types: nrow long

variable_types: ncol long

variable_types:
m
unsigned short **

return_type: unsigned short **


original_code:
unsigned short ***ui16colorim(long nrl, long nrh, long ncl, long nch)
{
 long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=3;
 unsigned short ***t;
 t=(unsigned short ***) malloc((size_t)((nrow+1)*sizeof(unsigned short**)));
 if (!t) iperror("allocation failure 1 in ui16colorim()");
 t += 1;
 t -= nrl;
 t[nrl]=(unsigned short **) malloc((size_t)((nrow*ncol+1)*sizeof(unsigned short*)));
 if (!t[nrl]) iperror("allocation failure 2 in ui16colorim()");
 t[nrl] += 1;
 t[nrl] -= ncl;
 t[nrl][ncl]=(unsigned short *) malloc((size_t)((nrow*ncol*ndep+1)*sizeof(unsigned short)));
 if (!t[nrl][ncl]) iperror("allocation failure 3 in ui16colorim()");
 t[nrl][ncl] += 1;
 t[nrl][ncl] -= 0;
 for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
 for(i=nrl+1;i<=nrh;i++) {
  t[i]=t[i-1]+ncol;
  t[i][ncl]=t[i-1][ncl]+ncol*ndep;
  for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
 }
 return t;
}

canonical_original_code:
unsigned short ***ui16colorim(long nrl, long nrh, long ncl, long nch)
{
 long i; long j; long nrow = nrh-nrl+1; long ncol = nch-ncl+1; long ndep = 3;
 unsigned short ***t;
 t=(unsigned short ***) malloc((unsigned long)((nrow+1)*sizeof(unsigned short **)));
 if (!t) iperror("allocation failure 1 in ui16colorim()");
 t += 1;
 t -= nrl;
 t[nrl]=(unsigned short **) malloc((unsigned long)((nrow*ncol+1)*sizeof(unsigned short *)));
 if (!t[nrl]) iperror("allocation failure 2 in ui16colorim()");
 t[nrl] += 1;
 t[nrl] -= ncl;
 t[nrl][ncl]=(unsigned short *) malloc((unsigned long)((nrow*ncol*ndep+1)*sizeof(unsigned short)));
 if (!t[nrl][ncl]) iperror("allocation failure 3 in ui16colorim()");
 t[nrl][ncl] += 1;
 t[nrl][ncl] -= 0;
 for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
 for(i=nrl+1;i<=nrh;i++) {
  t[i]=t[i-1]+ncol;
  t[i][ncl]=t[i-1][ncl]+ncol*ndep;
  for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
 }
 return t;
}

variable_types: j long

variable_types: ndep long

variable_types:
t
unsigned short ***

return_type: unsigned short ***


decompiled_code:
void __fastcall free_ui16vector(__int64 a1, __int64 a2)
{
free((void *)(a1 + 2 * a2 - 2));
}

canonical_decompiled_code:
void __fastcall func4(__int64 a1, __int64 a2)
{
free((void *)(a1 + 2 * a2 - 2));
}

original_code:
void free_ui16vector(unsigned short *v, long nl, long nh)
{
 free((char*) (v+nl-1));
}

canonical_original_code:
void free_ui16vector(unsigned short *v, long nl, long nh)
{
 free((char *) (v+nl-1));
}


original_code:
void free_ui16matrix(unsigned short **m, long nrl, long nrh, long ncl, long nch)
{
 free((char*) (m[nrl]+ncl-1));
 free((char*) (m+nrl-1));
}

canonical_original_code:
void free_ui16matrix(unsigned short **m, long nrl, long nrh, long ncl, long nch)
{
 free((char *) (m[nrl]+ncl-1));
 free((char *) (m+nrl-1));
}


original_code:
void free_ui16colorim(unsigned short ***t, long nrl, long nrh, long ncl, long nch)
{
 free((char*) (t[nrl][ncl]+0-1));
 free((char*) (t[nrl]+ncl-1));
 free((char*) (t+nrl-1));
}

canonical_original_code:
void free_ui16colorim(unsigned short ***t, long nrl, long nrh, long ncl, long nch)
{
 free((char *) (t[nrl][ncl]+0-1));
 free((char *) (t[nrl]+ncl-1));
 free((char *) (t+nrl-1));
}


autoexposure

decompiled_code:
__int64 __fastcall autoexposure(int a1, int a2, int a3, unsigned __int16 *a4, __int16 *a5)
{
unsigned int v7; // ebx
__int16 v8; // dx
unsigned __int16 v9; // bp
unsigned __int16 v10; // si
unsigned __int16 v11; // si
unsigned int v12; // ebx
__int64 result; // rax

v7 = (unsigned int)(a3 + a2 + a1) >> 18;
printf("image mean = %d targe = %d band=%d\n", v7, 683LL, 42LL);
v8 = *a5;
v9 = *a4;
v10 = *a4 * *a5;
if ( v7 > 0x2D5 )
{
v12 = 683 * (unsigned int)v10 / v7;
printf("current=%d new exposure=%d\n", v10, v12);
v8 = (unsigned __int16)v12 / v9;
if ( (unsigned __int16)((unsigned __int16)v12 / v9) <= 1u )
{
v9 = (unsigned __int16)v12 >> 1;
v8 = 2;
}
}
else if ( v7 <= 0x280 )
{
v11 = 683 * (unsigned int)v10 / v7;
v8 = v11 / v9;
if ( (unsigned __int16)(v11 / v9) > 0x64u )
{
v9 = v11 / 0x64u;
v8 = 100;
}
}
if ( !v9 )
v9 = 1;
*a5 = v8;
result = 16LL;
if ( v9 > 0x10u )
v9 = 16;
*a4 = v9;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1, int a2, int a3, unsigned __int16 *a4, __int16 *a5)
{
unsigned int v7; // ebx
__int16 v8; // dx
unsigned __int16 v9; // bp
unsigned __int16 v10; // si
unsigned __int16 v11; // si
unsigned int v12; // ebx
__int64 result; // rax

v7 = (unsigned int)(a3 + a2 + a1) >> 18;
printf("image mean = %d targe = %d band=%d\n", v7, 683LL, 42LL);
v8 = *a5;
v9 = *a4;
v10 = *a4 * *a5;
if ( v7 > 0x2D5 )
{
v12 = 683 * (unsigned int)v10 / v7;
printf("current=%d new exposure=%d\n", v10, v12);
v8 = (unsigned __int16)v12 / v9;
if ( (unsigned __int16)((unsigned __int16)v12 / v9) <= 1u )
{
v9 = (unsigned __int16)v12 >> 1;
v8 = 2;
}
}
else if ( v7 <= 0x280 )
{
v11 = 683 * (unsigned int)v10 / v7;
v8 = v11 / v9;
if ( (unsigned __int16)(v11 / v9) > 0x64u )
{
v9 = v11 / 0x64u;
v8 = 100;
}
}
if ( !v9 )
v9 = 1;
*a5 = v8;
result = 16LL;
if ( v9 > 0x10u )
v9 = 16;
*a4 = v9;
return result;
}

original_code:
void autoexposure(uint32_t rsum, uint32_t gsum, uint32_t bsum, uint16_t *Gain, uint16_t *Texp)
{
    uint32_t image_mean;
    uint16_t current_exposure;
    uint16_t new_exposure;
    uint16_t Te,G;
    uint32_t band;
    image_mean = (rsum+gsum+bsum) >> 18;
    band = (((((1<<10)-1)>>1)*724*484)>>18) >> 4;
    printf("image mean = %d targe = %d band=%d\n",image_mean,(((((1<<10)-1)>>1)*724*484)>>18),band);
    Te = *Texp; G = *Gain;
    current_exposure = Te * G;
    if (image_mean > ((((((1<<10)-1)>>1)*724*484)>>18) + band))
    {
        new_exposure = ((((((1<<10)-1)>>1)*724*484)>>18)*current_exposure)/image_mean;
        printf("current=%d new exposure=%d\n",current_exposure,new_exposure);
        Te = new_exposure/G;
        if (Te < 2)
        {
   Te = 2;
            G = new_exposure/Te;
        }
    } else {
             if (image_mean < (uint32_t)((((((1<<10)-1)>>1)*724*484)>>18) - band))
             {
                new_exposure = ((((((1<<10)-1)>>1)*724*484)>>18)*current_exposure)/image_mean;
                Te = new_exposure/G;
                if (Te > 100)
                {
       Te = 100;
                   G = new_exposure/Te;
                }
             }
    }
 if (G > 16)
  G = 16;
 if (G < 1)
  G = 1;
    *Texp = Te; *Gain = G;
}

canonical_original_code:
void autoexposure(unsigned int rsum, unsigned int gsum, unsigned int bsum, unsigned short *Gain, unsigned short *Texp)
{
    unsigned int image_mean;
    unsigned short current_exposure;
    unsigned short new_exposure;
    unsigned short Te; unsigned short G;
    unsigned int band;
    image_mean = (rsum+gsum+bsum) >> 18;
    band = (((((1<<10)-1)>>1)*724*484)>>18) >> 4;
    printf("image mean = %d targe = %d band=%d\n",image_mean,(((((1<<10)-1)>>1)*724*484)>>18),band);
    Te = *Texp; G = *Gain;
    current_exposure = Te * G;
    if (image_mean > ((((((1<<10)-1)>>1)*724*484)>>18) + band))
    {
        new_exposure = ((((((1<<10)-1)>>1)*724*484)>>18)*current_exposure)/image_mean;
        printf("current=%d new exposure=%d\n",current_exposure,new_exposure);
        Te = new_exposure/G;
        if (Te < 2)
        {
   Te = 2;
            G = new_exposure/Te;
        }
    } else {
             if (image_mean < (unsigned int)((((((1<<10)-1)>>1)*724*484)>>18) - band))
             {
                new_exposure = ((((((1<<10)-1)>>1)*724*484)>>18)*current_exposure)/image_mean;
                Te = new_exposure/G;
                if (Te > 100)
                {
       Te = 100;
                   G = new_exposure/Te;
                }
             }
    }
 if (G > 16)
  G = 16;
 if (G < 1)
  G = 1;
    *Texp = Te; *Gain = G;
}

variable_types:
rsum
unsigned int

variable_types:
gsum
unsigned int

variable_types:
bsum
unsigned int

variable_types:
Gain
unsigned short *

variable_types:
Texp
unsigned short *

variable_types:
Te
unsigned short

variable_types:
G
unsigned short

variable_types:
band
unsigned int


decompiled_code:
__int16 test_pattern_generator()
{
LSFR_0 = ((unsigned int)LSFR_0 >> 1) ^ -(LSFR_0 & 1) & 0xD0000001;
return LSFR_0 & 0x3FF;
}

canonical_decompiled_code:
__int16 func0()
{
LSFR_0 = ((unsigned int)LSFR_0 >> 1) ^ -(LSFR_0 & 1) & 0xD0000001;
return LSFR_0 & 0x3FF;
}

original_code:
uint16_t test_pattern_generator(void)
{
    uint16_t pixel;
    static unsigned int LSFR = 1u;
    LSFR = (LSFR >>1) ^ ((-(LSFR & 1u)) & 0xD0000001u);
    pixel = (LSFR & ((1<<10)-1));
    return pixel;
}

canonical_original_code:
unsigned short test_pattern_generator()
{
    unsigned short pixel;
    static unsigned int LSFR = 1u;
    LSFR = (LSFR >>1) ^ ((-(LSFR & 1u)) & 0xD0000001u);
    pixel = (LSFR & ((1<<10)-1));
    return pixel;
}

variable_types:
pixel
unsigned short

variable_types:
LSFR
unsigned int

return_type: unsigned short


comp

repo: sharow/libconcurrent

decompiled_code:
__int64 __fastcall comp(const void *a1, const void *a2)
{
int v2; // ebp
int v3; // ebx

v2 = *(_DWORD *)a1;
v3 = *(_DWORD *)a2;
concurrent_yield(g_context);
if ( v2 > v3 )
return 1LL;
if ( v2 < v3 )
return 0xFFFFFFFFLL;
if ( v2 != v3 )
__assert_fail("!\"not reached\"", "concurrent_sort1.c", 0x26u, "comp");
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func7(const void *a1, const void *a2)
{
int v2; // ebp
int v3; // ebx

v2 = *(_DWORD *)a1;
v3 = *(_DWORD *)a2;
func21(g_context);
if ( v2 > v3 )
return 1LL;
if ( v2 < v3 )
return 0xFFFFFFFFLL;
if ( v2 != v3 )
__assert_fail("!\"not reached\"", "concurrent_sort1.c", 0x26u, "comp");
return 0LL;
}

original_code:
int comp(const void *value0, const void *value1)
{
    int a = *(const int *)value0;
    int b = *(const int *)value1;
    concurrent_yield(g_context);
    if (a > b) {
        return 1;
    } else if (a < b) {
        return -1;
    } else if (a == b) {
        return 0;
    }
    ((!"not reached") ? (void) (0) : __assert_fail ("!\"not reached\"", "concurrent_sort1.c", 38, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

canonical_original_code:
int comp(void *value0, void *value1)
{
    int a = *(const int *)value0;
    int b = *(const int *)value1;
    concurrent_yield(g_context);
    if (a > b) {
        return 1;
    } else if (a < b) {
        return -1;
    } else if (a == b) {
        return 0;
    }
    ((!"not reached") ? (void) (0) : __assert_fail ("!\"not reached\"", "concurrent_sort1.c", 38, __extension__ __PRETTY_FUNCTION__));
    return 0;
}

variable_types: a int

variable_types: b int

return_type: int


decompiled_code:
int __fastcall print_datas(__int64 a1)
{
__int64 v1; // rbx
int result; // eax

if ( *(int *)(a1 + 8) > 0 )
{
v1 = 0LL;
do
result = printf("%d ", *(unsigned int *)(*(_QWORD *)a1 + 4 * v1++));
while ( *(_DWORD *)(a1 + 8) > (int)v1 );
}
return result;
}

canonical_decompiled_code:
int __fastcall func9(__int64 a1)
{
__int64 v1; // rbx
int result; // eax

if ( *(int *)(a1 + 8) > 0 )
{
v1 = 0LL;
do
result = printf("%d ", *(unsigned int *)(*(_QWORD *)a1 + 4 * v1++));
while ( *(_DWORD *)(a1 + 8) > (int)v1 );
}
return result;
}

original_code:
void print_datas(struct sort_ctx *sort_ctx)
{
    int i;
    for (i = 0; i < sort_ctx->num_data; i++) {
        printf("%d ", sort_ctx->data[i]);
    }
}

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

variable_types: i int


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t v3; // rax
void *v4; // rbp
void *v5; // rbx
float v6; // xmm0_4
__int64 v7; // rax
int *v9; // [rsp+0h] [rbp-68h] BYREF
int v10; // [rsp+8h] [rbp-60h]
int v11[22]; // [rsp+10h] [rbp-58h] BYREF

v11[0] = 12;
v11[1] = 13;
v11[2] = 14;
v11[3] = 15;
v11[4] = 10;
v11[5] = 9;
v11[6] = 7;
v11[7] = 1;
v11[8] = 2;
v11[9] = 11;
v11[10] = 3;
v11[11] = 4;
v11[12] = 8;
v11[13] = 6;
v11[14] = 5;
v11[15] = 0;
v9 = v11;
v10 = 16;
concurrent_init(argc, argv, envp);
v3 = concurrent_sizeof();
v4 = malloc(v3);
g_context = v4;
v5 = malloc(0x1000uLL);
concurrent_construct(v4, v5, 4096LL, coro, &v9);
while ( !(unsigned __int8)concurrent_is_done(g_context) )
{
v7 = concurrent_get_stack_used(g_context);
if ( v7 < 0 )
v6 = (float)(v7 & 1 | (unsigned int)((unsigned __int64)v7 >> 1))
+ (float)(v7 & 1 | (unsigned int)((unsigned __int64)v7 >> 1));
else
v6 = (float)(int)v7;
printf("stack used:%3zdbytes(%2.0f%%); data={ ", v7, (float)((float)(v6 * 0.00024414062) * 100.0));
print_datas((__int64)&v9);
puts("}");
concurrent_resume(g_context);
}
concurrent_destruct(g_context);
free(v5);
free(g_context);
concurrent_fin();
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; }


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
return concurrent_arch_setup_execution_context();
}

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; } *

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; }


panic

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

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

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

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


decompiled_code:
void concurrent_fin()
{
;
}

canonical_decompiled_code:
void func13()
{
;
}

original_code:
void
concurrent_fin(void)
{
}

canonical_original_code:
void concurrent_fin()
{
}


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

canonical_decompiled_code:
__int64 func14()
{
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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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 )
panic();
}
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 func18(__int64 a1)
{
return func17(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 func19(__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 )
panic();
*(_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 func21(__int64 a1)
{
return func20(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 func22(__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 )
panic();
*(_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 func24(__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 func25(__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 )
panic(a1);
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 func27(__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;
}


main

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

concurrent_init(argc, argv, envp);
v3 = strsplit_new((__int64)"monday|tuesday|wednesday|thursday|friday|saturday|sunday", 124);
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)
{
_QWORD *v3; // rbx
__int64 v4; // rax

func12(argc, argv, envp);
v3 = strsplit_new((__int64)"monday|tuesday|wednesday|thursday|friday|saturday|sunday", 124);
while ( 1 )
{
v4 = func9(v3);
if ( !v4 )
break;
printf("%.*s\n", *(_QWORD *)(v4 + 8), *(const char **)v4);
}
func8(v3);
func13();
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)
{
*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
return concurrent_arch_setup_execution_context();
}

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


panic

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

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


decompiled_code:
void concurrent_fin()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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 )
panic();
}
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);
}

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);
}

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 )
panic();
*(_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);
}

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 )
panic();
*(_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);
}

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;
}

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 )
panic(a1);
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);
}

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


main

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

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

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

func10(argc, argv, envp);
v3 = func12();
v4 = malloc(v3);
v5 = malloc(0x800uLL);
v11 = "A";
func13(v4, v5, 2048LL, task, &v11);
v6 = func12();
v7 = malloc(v6);
v8 = malloc(0x800uLL);
v12 = "B";
func13(v7, v8, 2048LL, task, &v12);
v9 = 10;
do
{
puts("main:");
func16(v4);
puts("main:");
func16(v7);
--v9;
}
while ( v9 );
puts("finish");
func14(v7);
free(v8);
free(v7);
func14(v4);
free(v5);
free(v4);
func11();
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;
}


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
return concurrent_arch_setup_execution_context();
}

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


panic

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

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

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


decompiled_code:
void concurrent_fin()
{
;
}

canonical_decompiled_code:
void func11()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


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

canonical_decompiled_code:
__int64 func12()
{
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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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 )
panic();
}
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 func16(__int64 a1)
{
return func15(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 func17(__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 )
panic();
*(_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 func19(__int64 a1)
{
return func18(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 func20(__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 )
panic();
*(_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 func22(__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 func23(__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 )
panic(a1);
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 func25(__int64 a1)
{
return *(_QWORD *)(a1 + 16);
}

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


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));
func10();
func13(v6, v8, 2048LL, accumulator, 0LL);
for ( i = 1; i <= 10; ++i )
{
v4 = (unsigned int *)func15(v6, &i);
printf("total = %d\n", *v4);
}
func14(v6);
func11();
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;
}


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
return concurrent_arch_setup_execution_context();
}

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


panic

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

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


decompiled_code:
void concurrent_fin()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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 )
panic();
}
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);
}

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);
}

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 )
panic();
*(_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);
}

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 )
panic();
*(_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);
}

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;
}

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 )
panic(a1);
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);
}

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


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
time_t v3; // rdi
int v4; // er12
size_t v5; // rbx
__int64 v6; // rbp
size_t v7; // rax
void *v8; // r13
char *v9; // r14
bool v10; // cf
bool v11; // zf
const char *v12; // rsi
const char *v13; // rdi
__int64 v14; // rcx

v3 = time(0LL);
srand(v3);
concurrent_init(v3, argv);
v4 = 1000;
do
{
v5 = rand() % 16 + 1040;
v6 = rand() % 16;
v7 = concurrent_sizeof();
v8 = malloc(v7);
v9 = (char *)malloc(v5);
if ( (unsigned int)concurrent_construct(v8, &v9[v6], v5 - v6, test_generator, 0LL) )
__assert_fail("status == CONCURRENT_SUCCESS", "stack_torture1.c", 0x25u, "main");
v12 = (const char *)concurrent_resume(v8);
v13 = "pong";
v14 = 5LL;
do
{
if ( !v14 )
break;
v10 = *v12 < (unsigned int)*v13;
v11 = *v12++ == *v13++;
--v14;
}
while ( v11 );
if ( (!v10 && !v11) != v10 )
__assert_fail("strcmp(resume(ctx), \"pong\") == 0", "stack_torture1.c", 0x26u, "main");
concurrent_destruct(v8, v12);
free(v9);
free(v8);
--v4;
}
while ( v4 );
concurrent_fin();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
time_t v3; // rdi
int v4; // er12
size_t v5; // rbx
__int64 v6; // rbp
size_t v7; // rax
void *v8; // r13
char *v9; // r14
bool v10; // cf
bool v11; // zf
const char *v12; // rsi
const char *v13; // rdi
__int64 v14; // rcx

v3 = time(0LL);
srand(v3);
func10(v3, argv);
v4 = 1000;
do
{
v5 = rand() % 16 + 1040;
v6 = rand() % 16;
v7 = func12();
v8 = malloc(v7);
v9 = (char *)malloc(v5);
if ( (unsigned int)func13(v8, &v9[v6], v5 - v6, test_generator, 0LL) )
__assert_fail("status == CONCURRENT_SUCCESS", "stack_torture1.c", 0x25u, "main");
v12 = (const char *)func16(v8);
v13 = "pong";
v14 = 5LL;
do
{
if ( !v14 )
break;
v10 = *v12 < (unsigned int)*v13;
v11 = *v12++ == *v13++;
--v14;
}
while ( v11 );
if ( (!v10 && !v11) != v10 )
__assert_fail("strcmp(resume(ctx), \"pong\") == 0", "stack_torture1.c", 0x26u, "main");
func14(v8, v12);
free(v9);
free(v8);
--v4;
}
while ( v4 );
func11();
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;
}


decompiled_code:
__int64 __fastcall concurrent_setup_execution_context(__int64 a1)
{
*(_QWORD *)(a1 + 40) = *(_QWORD *)(a1 + 32);
return concurrent_arch_setup_execution_context();
}

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


panic

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

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


decompiled_code:
void concurrent_fin()
{
;
}

original_code:
void
concurrent_fin(void)
{
}


decompiled_code:
__int64 concurrent_sizeof()
{
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

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 = a4;
*(_QWORD *)(a1 + 8) = a5;
*(_QWORD *)(a1 + 16) = a2;
v6 = (a3 + a2 - v5) & 0xFFFFFFFFFFFFFFF0LL;
*(_QWORD *)(a1 + 24) = v6;
*(_QWORD *)(a1 + 32) = v5 + v6;
*(_QWORD *)(a1 + 40) = 0LL;
*(_DWORD *)(a1 + 48) = 0;
*(_QWORD *)(a1 + 56) = 0LL;
*(_QWORD *)(a1 + 64) = 0LL;
*(_QWORD *)(a1 + 72) = 0LL;
return 0LL;
}

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 )
panic();
}
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);
}

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);
}

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 )
panic();
*(_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);
}

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 )
panic();
*(_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);
}

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;
}

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 )
panic(a1);
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);
}

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