<commit_before>#include "flow-graph.h"

#define _LJIT_LABEL_FG_INIT(size)                       \
    _ljit_label_fg_node(1, 0, 0, size, NULL, NULL)

#define _LJIT_LABEL_FG_FREE()                           \
    _ljit_label_fg_node(0, 1, 0, 0, NULL, NULL)

#define _LJIT_LABEL_FG_GET(label, fun)                  \
    _ljit_label_fg_node(0, 0, 0, 0, label, fun)

#define _LJIT_LABEL_FG_GET_INDEX(index, fun)                  \
    _ljit_label_fg_node(0, 0, 1, index, NULL, fun)

static int _ljit_fg_index()
{
    static int i = -1;

    ++i;

    return i;
}

static ljit_flow_graph *_ljit_label_fg_node(unsigned int init,
                                            unsigned int destroy,
                                            unsigned int set,
                                            unsigned int number_tmp,
                                            ljit_label *l,
                                            ljit_function *fun)
{
    static unsigned int size = 0;
    static ljit_flow_graph ** fg = NULL;

    if (init)
    {
        size = number_tmp;
        fg = calloc(1, size * sizeof(ljit_flow_graph *));
        return NULL;
    }
    else if (destroy)
    {
        free(fg);
        return NULL;
    }
    else
    {
        unsigned int label_num = 0;
        ljit_block *b = NULL;

        if (set)
        {
            label_num = number_tmp;
            b = ljit_get_block_from_label_num(fun, label_num);
        }
        else
        {
            label_num = l->index;
            b = ljit_get_block_from_label(fun, l);
        }

        if (!fg[label_num])
        {
            if (!b)
                return NULL;

            fg[label_num] = _ljit_new_flow_graph(b->instrs->head->instr);

            if (!fg[label_num])
                return NULL;
        }

        return fg[label_num];
    }
}

ljit_flow_graph *_ljit_new_flow_graph(ljit_bytecode *instr)
{
    ljit_flow_graph *fg = NULL;

    if ((fg = malloc(sizeof(ljit_flow_graph))) == NULL)
        return NULL;

    fg->instr = instr;
    fg->first_next = NULL;
    fg->second_next = NULL;
    fg->index = _ljit_fg_index();
    fg->marked = 0;

    return fg;
}

void _ljit_free_flow_graph(ljit_flow_graph *fg)
{
    if (!fg)
        return;

    _ljit_free_flow_graph(fg->first_next);
    _ljit_free_flow_graph(fg->second_next);
    free(fg);
}

static ljit_flow_graph *
_ljit_recurse_build_fg(ljit_block *blk,
                       struct _ljit_bytecode_list_element_s *tmp_instr,
                       ljit_function *fun)
{
    ljit_flow_graph *fg = NULL;
    ljit_flow_graph *second = NULL;

    if (!tmp_instr)
    {
        if (!blk->next)
            return NULL;
        else
            return _ljit_recurse_build_fg(blk->next, blk->next->instrs->head,
                                          fun);
    }

    switch (tmp_instr->instr->type)
    {
        case JUMP:
            {
                ljit_block *b = ljit_get_block_from_label(fun,
                                                          (ljit_label*)tmp_instr->instr->op1);

                if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                    goto error;

                fg->marked = 1;

                fg->first_next = _ljit_recurse_build_fg(b, b->instrs->head,
                                                        fun);

                return fg;
            }
            break;
        case JUMP_IF:
        case JUMP_IF_NOT:
            {
                ljit_block *b = ljit_get_block_from_label(fun,
                                                          (ljit_label*)tmp_instr->instr->op2);
                if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                    goto error;

                fg->marked = 1;

                second = _ljit_recurse_build_fg(b, b->instrs->head, fun);
            }
            break;
        case LABEL:
            fg = _LJIT_LABEL_FG_GET_INDEX(*(ljit_int*)tmp_instr->instr->op1,
                                         fun);
            if (fg->marked)
                return fg;

            break;
        default:
            if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                goto error;
            fg->marked = 1;
            break;
    }

    fg->marked = 1;
    fg->first_next = _ljit_recurse_build_fg(blk, tmp_instr->next, fun);
    fg->second_next = second;

    return fg;

error:
    free(fg);
    return NULL;
}

ljit_flow_graph *_ljit_build_flow_graph(ljit_function *fun)
{
    ljit_flow_graph *fg = NULL;

    _LJIT_LABEL_FG_INIT(fun->lbl_index);
<commit_msg>[CORE] Fix bugs in control flow graph builder<commit_after>#include "flow-graph.h"

#define _LJIT_LABEL_FG_INIT(size)                       \
    _ljit_label_fg_node(1, 0, size, NULL, NULL)

#define _LJIT_LABEL_FG_FREE()                           \
    _ljit_label_fg_node(0, 1, 0, NULL, NULL)

#define _LJIT_LABEL_FG_GET(label, fun)                  \
    _ljit_label_fg_node(0, 0, 0, label, fun)

static int _ljit_fg_index()
{
    static int i = -1;

    ++i;

    return i;
}

static ljit_flow_graph *_ljit_label_fg_node(unsigned int init,
                                            unsigned int destroy,
                                            unsigned int number_tmp,
                                            ljit_label *l,
                                            ljit_function *fun)
{
    static unsigned int size = 0;
    static ljit_flow_graph ** fg = NULL;

    if (init)
    {
        size = number_tmp;
        fg = calloc(1, size * sizeof(ljit_flow_graph *));
        return NULL;
    }
    else if (destroy)
    {
        free(fg);
        return NULL;
    }
    else
    {
        unsigned int label_num = l->index;

        if (!fg[label_num])
        {
            ljit_block *b = ljit_get_block_from_label(fun, l);

            if (!b)
                return NULL;

            fg[label_num] = _ljit_new_flow_graph(b->instrs->head->instr);

            if (!fg[label_num])
                return NULL;
        }

        return fg[label_num];
    }
}

ljit_flow_graph *_ljit_new_flow_graph(ljit_bytecode *instr)
{
    ljit_flow_graph *fg = NULL;

    if ((fg = malloc(sizeof(ljit_flow_graph))) == NULL)
        return NULL;

    fg->instr = instr;
    fg->first_next = NULL;
    fg->second_next = NULL;
    fg->index = _ljit_fg_index();
    fg->marked = 0;

    return fg;
}

void _ljit_free_flow_graph(ljit_flow_graph *fg)
{
    if (!fg || fg->marked)
        return;

    fg->marked = 1;
    _ljit_free_flow_graph(fg->first_next);
    _ljit_free_flow_graph(fg->second_next);
    free(fg);
}

static ljit_flow_graph *
_ljit_recurse_build_fg(ljit_block *blk,
                       struct _ljit_bytecode_list_element_s *tmp_instr,
                       ljit_function *fun)
{
    ljit_flow_graph *fg = NULL;
    ljit_flow_graph *second = NULL;

    if (!tmp_instr)
    {
        if (!blk->next)
            return NULL;
        else
            return _ljit_recurse_build_fg(blk->next, blk->next->instrs->head,
                                          fun);
    }

    switch (tmp_instr->instr->type)
    {
        case JUMP:
            {
                ljit_label *l = tmp_instr->instr->op1->data;
                ljit_block *b = ljit_get_block_from_label(fun, l);

                if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                    goto error;

                fg->marked = 1;

                fg->first_next = _ljit_recurse_build_fg(b, b->instrs->head,
                                                        fun);

                return fg;
            }
            break;
        case JUMP_IF:
        case JUMP_IF_NOT:
            {
                ljit_label *l = tmp_instr->instr->op2->data;
                ljit_block *b = ljit_get_block_from_label(fun, l);

                if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                    goto error;

                fg->marked = 1;

                second = _ljit_recurse_build_fg(b, b->instrs->head, fun);
            }
            break;
        case LABEL:
            {
                ljit_label *l = tmp_instr->instr->op1->data;

                fg = _LJIT_LABEL_FG_GET(l, fun);

                if (fg->marked)
                    return fg;
            }
            break;
        default:
            if ((fg = _ljit_new_flow_graph(tmp_instr->instr)) == NULL)
                goto error;

            break;
    }

    fg->marked = 1;
    fg->first_next = _ljit_recurse_build_fg(blk, tmp_instr->next, fun);
    fg->second_next = second;

    return fg;

error:
    free(fg);
    return NULL;
}

ljit_flow_graph *_ljit_build_flow_graph(ljit_function *fun)
{
    ljit_flow_graph *fg = NULL;

    _LJIT_LABEL_FG_INIT(fun->lbl_index);

{'fraction_non_alphanumeric': 0.09981726815897671, 'fraction_numerical': 0.005139333028780265, 'mean_word_length': 1.429126213592233, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6399222', 'n_tokens_mistral': 3024, 'n_tokens_neox': 2823, 'n_words': 526}