Esempio n. 1
0
    def _make_accessors(self, info):
        """Build get() and set() function based on info.
        """
        name = self._array_name(info)
        fname = self._make_getter_name(info)
        size = info.sizeof()
        params = [("int", f"x{i}") for i in range(len(info.size))]
        mults = [
            BinaryOp("*", a, ID(b[1]))
            for a, b in zip(info.size[1:], params[:-1])
        ]

        offset = ID(params[-1][1])
        for m in mults:
            offset = BinaryOp("+", m, offset)

        cases = [
            Case(Constant("int", str(i)), [Return(ID(f"{name}_{i}"))])
            for i in range(size)
        ]
        body = Compound([Switch(offset, Compound(cases))])
        self.accessors.add(make_function(info.type, fname, params, body))

        cases = [
            Case(Constant("int", str(i)),
                 [Assignment("=", ID(f"{name}_{i}"), ID("value")),
                  Break()]) for i in range(size)
        ]
        body = Compound([Switch(offset, Compound(cases))])
        type_ = (info.type.name
                 if type(info.type) == Struct else info.type.names[0])
        setter = make_function(IdentifierType(["void"]),
                               fname.replace("get", "set", 1),
                               params + [(type_, "value")], body)
        self.accessors.add(setter)
def modify_block(ast_tree, epoch, epoch_name):
    """
    modifies the block, assigns the bB variable properly
    :param ast_tree:
    :param epoch:
    :param epoch_name:
    :return:
    """
    parent_comp = find_parent(ast_tree, epoch)
    epoch_index = parent_comp.block_items.index(epoch)
    cond = BinaryOp('!=', ID('iter'), ID(epoch_name))

    new_if = If(cond, None, None, epoch.coord)
    assign_unique_coord(new_if, epoch.coord)

    assign_b_tofalse = create_new_assign('false', 'b' + str(var_b),
                                         epoch.coord)
    assign_unique_coord(assign_b_tofalse, epoch.coord)
    assign_b_totrue = create_new_assign('true', 'b' + str(var_b), epoch.coord)
    assign_unique_coord(assign_b_totrue, epoch.coord)

    cont = Continue(epoch.coord)

    if_true = Compound([assign_b_tofalse, cont], epoch.coord)
    assign_unique_coord(if_true, epoch.coord)

    if_false = Compound([assign_b_totrue], epoch.coord)
    assign_unique_coord(if_false, epoch.coord)

    new_if.iftrue = if_true
    new_if.iffalse = if_false

    parent_comp.block_items.insert(epoch_index + 1, new_if)
Esempio n. 3
0
 def cached_provider_call(self):
     provider = self.provider
     entity_flag = self.memo_flag_name
     return If(cond=UnaryOp(op='!', expr=ID(name=entity_flag)),
               iftrue=Compound(block_items=[ FuncCall(name=ID(name=provider), args=None),
                                             Assignment(op='=',
                                                        lvalue=ID(name=entity_flag),
                                                        rvalue=Constant(type='bool', value='true'))]),
               iffalse=None)
Esempio n. 4
0
 def touch_definition_node(self):
     type_ = FuncDecl(args=None,
                      type=TypeDecl(declname=self.c_touch_name,
                                    quals=[], type=IdentifierType(names=['void'])))
     return FuncDef(decl=Decl(name=self.c_touch_name,
                              quals=[], storage=[],
                              funcspec=[], type=type_,
                              init=None, bitsize=None),
                    param_decls=None, body=Compound(block_items=[]))
def more_epoch_jumps(ast_tree, epoch_name):
    new_ast = duplicate_element(ast_tree)
    epoch_jumps = get_epochs_assigns(get_extern_while_body(ast_tree),
                                     epoch_name)
    epoch_jumps.reverse()
    coord = epoch_jumps[0].coord

    insert_assigns(new_ast, epoch_name, len(epoch_jumps))

    ifs_list = []
    for i in xrange(len(epoch_jumps)):
        block_b = identify_block_b(ast_tree, epoch_jumps[i], epoch_name)
        new_if = create_blockb_if(block_b, epoch_jumps[i])
        ifs_list.append(new_if)

    remaining_code = get_extern_while_body(ast_tree)

    cond = BinaryOp('==', ID('iter'), ID(epoch_name))
    iter_if = If(cond, None, None)
    assign_unique_coord(iter_if, coord)

    ifs_list[-1].iffalse = remaining_code
    for i in xrange(len(ifs_list)):
        if i + 1 in xrange(len(ifs_list)):
            comp = Compound([ifs_list[i + 1]])
            ifs_list[i].iffalse = comp

    aux = ifs_list[0]

    new_comp = Compound([aux])
    iter_if.iftrue = new_comp

    iter_inc = UnaryOp('p++', ID('iter'), coord)  # iter ++
    assign_unique_coord(iter_inc, coord)

    new_while_body = Compound([iter_inc, iter_if], coord)

    body = get_extern_while_body(new_ast)
    body.block_items = new_while_body

    # print generator.visit(new_ast)
    return new_ast
def create_blockb_if(block_b, epoch):
    """
    creates the if from the bB block
    :param block_b:
    :param epoch:
    :return:
    """
    global var_b

    new_cond = UnaryOp('!', ID('b' + str(var_b)))

    iffalse_comp = Compound([], epoch.coord)

    new_if = If(new_cond, block_b, iffalse_comp, epoch.coord)
    assign_unique_coord(new_if, epoch.coord)

    return new_if
Esempio n. 7
0
 def visit_Compound(self, node: c_ast.Compound):
     # TODO: currently doesn't support ArrayRef
     # only generate shadow execution for dynamically tracked variables
     node.block_items = [
         child for child in node.block_items
         if isinstance(child, c_ast.Assignment)
         and child.lvalue.name in self._shadow_variables
     ]
     for child in node:
         if isinstance(child, c_ast.Assignment):
             child.rvalue = c_ast.BinaryOp(
                 op='-',
                 left=self._expression_replacer.visit(child.rvalue),
                 right=c_ast.ID(name=child.lvalue.name))
             # change the assignment variable name to shadow distance variable
             child.lvalue.name = f'{constants.SHADOW_DISTANCE}_{child.lvalue.name}'
         else:
             self.visit(child)
def identify_block_b(ast, epoch, epoch_name):
    """
    identifies and creates the bB block
    :param ast:
    :param epoch:
    :param epoch_name:
    :return:
    """
    global var_b
    ast_tree = duplicate_element(ast)
    parent_comp = find_parent(ast_tree, epoch)
    parent = find_parentUpdated(ast_tree, epoch)
    # print generator.visit(parent_comp)
    epoch_index = parent_comp.block_items.index(epoch)
    to_add = parent_comp.block_items[epoch_index + 1:]

    changed_parent = True
    while changed_parent:
        grandparent_comp = find_parent(ast_tree, parent)
        grandparent = find_parentUpdated(ast_tree, parent)

        # print type(grandparent_comp.block_items)
        # print generator.visit(grandparent_comp)
        # print generator.visit(parent)
        index = grandparent_comp.block_items.index(parent)
        to_add = to_add + grandparent_comp.block_items[index + 1:]
        parent = grandparent
        if grandparent_comp == grandparent:
            changed_parent = False
        # print index

    block_b = Compound(to_add, epoch.coord)
    assign_unique_coord(block_b, epoch.coord)

    var_b += 1

    assign = create_new_assign('true', 'b' + str(var_b),
                               epoch.coord)  # create assign b = true
    assign_unique_coord(assign, epoch.coord)
    block_b.block_items.insert(len(block_b.block_items), assign)
    modify_block(ast, epoch, epoch_name)

    return block_b
Esempio n. 9
0
def parse_compound(block: Compound, parents: list, globals: list):
    """
    Parses through the block, registering any local variables it finds and running itself recursively on any sub-blocks.
    :param block:
    :param parents:
    :param globals:
    :return:
    """

    if len(parents) == 0:
        block.parent = None
    else:
        block.parent = parents[-1]

    for statement in block.block_items:
        if isinstance(statement, Decl):
            # A Decl statement, so a local variable needs to be added to the block.

            # Get the variable's name
            name = statement.name

            # The type declaration, either in statement.type or, if a pointer, statement.type.type.
            if isinstance(statement.type, PtrDecl):
                typedecl = statement.type.type
            else:
                typedecl = statement.type

            # Get the variable's type - more complicated
            try:
                type_name = get_type_name(typedecl)
            except UnknownTypeException as err:
                logging.error(
                    "Unknown type for variable {name}: {type}".format(
                        name=name, type=err.type_list))
                continue

            if isinstance(statement.type, PtrDecl):
                type_name += "*"

            # The initial value
            initial = statement.init

            # Actually add it to the block
            block.locals.append(LocalVariable(name, type_name, initial))

        # Recursively call the sub-blocks of compound types
        elif isinstance(statement, If):
            parse_compound(statement.iftrue, parents + [block], globals)
            parse_compound(statement.iffalse, parents + [block], globals)
        elif isinstance(statement, (For, While)):
            parse_compound(statement.stmt, parents + [block], globals)

        # Other types of statement to analyse for references to variables
        else:
            for var in variable_search(statement):
                decl = climbing_variable_search(var, parents + [block])
                if decl is None:
                    # Maybe try the globals?
                    for var_decl in globals:
                        if var_decl[0] == var:
                            decl = var_decl
                # Still None? it wasn't found.
                if decl is None:
                    logging.error("Variable not found: {}".format(var))
def identify_nested(ast_tree):
    ast = ast_tree
    old_stdout = sys.stdout
    sys.stdout = mystdout = StringIO()
    aux_ast = duplicate_element(ast)
    list = []
    extern_while = get_extern_while_body(aux_ast)
    identify_nested_algorithms_bodies(extern_while, list)

    labelname_inner = config.variables_2['round']
    rounds_list_inner = config.rounds_list_2
    delete_round_phase_inner = config.delete_round_phase
    message_inner = config.msg_structure_fields_2
    variables_inner = config.variables_2

    if list:
        list.reverse()
        labels = config.rounds_list_2
        labels.append('ERR_ROUND')
        code = None
        cop = duplicate_element(ast)
        if len(list) >= config.number_of_nested_algorithms:
            extern = get_extern_while_body(cop)
            if isinstance(extern.block_items[0], If):
                myif = extern.block_items[0]
                list1 = []
                list2 = []
                aux1 = []
                aux2 = []
                identify_nested_algorithms_bodies(extern.block_items[0].iftrue,
                                                  list1)
                if list1:
                    sys.stdout = old_stdout

                    for elem in list1:
                        conditii = []
                        whiles_to_if(elem.stmt, conditii)
                        identify_recv_exits(elem.stmt, conditii)
                        remove_mbox(elem.stmt, config.mailbox_2,
                                    config.clean_mailbox_2)
                        aux1 = elem.stmt

                        parent = find_parent(ast, elem)
                        index = parent.block_items.index(elem)
                        parent.block_items.remove(elem)
                        coord = elem.coord
                        new_id = ID("inner_algorithm", coord)
                        func = FuncCall(new_id, None, coord)
                        assign_unique_coord(func, coord)
                        parent.block_items.insert(index, func)

                identify_nested_algorithms_bodies(
                    extern.block_items[0].iffalse, list2)
                if list2:
                    for elem in list2:
                        conditii = []
                        whiles_to_if(elem.stmt, conditii)
                        identify_recv_exits(elem.stmt, conditii)
                        remove_mbox(elem.stmt, config.mailbox_2,
                                    config.clean_mailbox_2)
                        aux2 = elem.stmt

                        parent = find_parent(ast, elem)
                        index = parent.block_items.index(elem)
                        parent.block_items.remove(elem)
                        coord = elem.coord
                        new_id = ID("inner_algorithm", coord)
                        func = FuncCall(new_id, None, coord)
                        assign_unique_coord(func, coord)
                        parent.block_items.insert(index, func)
                if aux1 and aux2:
                    myif.iftrue = None
                    myif.iffalse = None
                    myif.iftrue = aux1
                    myif.iffalse = aux2

                    trees_dict, trees_paths_dict, is_job = get_paths_trees(
                        cop, labels, labels, config.variables_2['round'])

                    print_rounds(labels, trees_dict, trees_paths_dict,
                                 config.variables_2['round'], is_job,
                                 delete_round_phase_inner, message_inner,
                                 variables_inner, rounds_list_inner[0])

                    code = mystdout.getvalue()
                    sys.stdout = old_stdout

                    return ast, code

        else:
            for elem in list:
                # print generator.visit(elem), "AAAAAAAAAAA"
                conditii = []
                whiles_to_if(elem.stmt, conditii)

                identify_recv_exits(elem.stmt, conditii)
                remove_mbox(elem.stmt, config.mailbox_2,
                            config.clean_mailbox_2)
                # print generator.visit(elem)
                trees_dict, trees_paths_dict, is_job = get_paths_trees(
                    elem.stmt, labels, labels, config.variables_2['round'])
                # print_code(trees_dict, trees_paths_dict, labels)

                print_rounds(labels, trees_dict, trees_paths_dict,
                             config.variables_2['round'], is_job,
                             delete_round_phase_inner, message_inner,
                             variables_inner, rounds_list_inner[0])
                parent = find_parent(ast, elem)
                index = parent.block_items.index(elem)
                parent.block_items.remove(elem)

                coord = elem.coord

                new_id = ID("inner_algorithm", coord)
                func = FuncCall(new_id, None, coord)
                assign_unique_coord(func, coord)
                parent.block_items.insert(index, func)
                # print generator.visit(parent.block_items[index])
                # print generator.visit(ast)
                # print generator.visit(func)

                funcdecl = FuncDecl(
                    None,
                    TypeDecl('inner_algorithm', None, IdentifierType(['int'])))
                decl = Decl('inner_algorithm', None, None, None, funcdecl,
                            None, None)
                funcdef = FuncDef(decl, None, None)
                code = mystdout.getvalue()
                funcdef.body = Compound([code])

                # print generator.visit(ast)

            sys.stdout = old_stdout
            return ast, code
    else:
        sys.stdout = old_stdout
        print "pe else"
        return ast_tree
Esempio n. 11
0
def find_all_paths_util(current_node, source_node, dest_node, path, parent_list, grandparent_list,
                        paths_list, source_reached, tree, last_if, parent_index, last_if_child, is_job):
    """

    :param current_node: program's extern while loop body just pruned with prune_tree function in the first place, then
    changes at each recursive call
    :param source_node: currently used with Assignment object, but it can be anything
    :param dest_node: currently used with Assignment object, but it can be anything
    :param path: a list where all the nodes along the path are stored
    :param parent_list: a list with all the parents that were visited
    :param grandparent_list: a list with all the grandparents that were visited
            If after visiting the children of a node we want to continue the search,
            we have to move to the next brother on the right side of that node. So we identify
            that brother by knowing the parent - the node that was just visited - and the grandparent, i.e,
            the parent of the if node
    :param paths_list: a list of tuples; a tuple is a pair of (tree, path), where the path is the path argument, i.e,
     a list of nodes and the tree is a clone of original tree modified to reflect the path. So each valid path
     discovered has its own tree.
    :param source_reached: boolean var that is set to True if the source was reached
    :param tree: the tree we are currently working with; for each modification, a clone is created, the nodes are
    moved/deleted/inserted by the case and the clone (now modified) is passed to the next recursive call
    :param last_if: a reference to an If node; the new discovered nodes have to be moved from their current place
     to become his children; if this argument is None, the discovered nodes remain in their places. it changes
     from None when an artificial else branch is created or there is a jump of rounds or a blocking while loop
    :param parent_index: sometimes the node of which the next right side brother is needed to continue the search
    is already deleted, so we have to keep in this list the node's old index so we can still detect his right
    side brother
    :param last_if_child: boolean var that is set according to the position of the current node as a child of his parent.
    if the current node is not the rightmost child of his parent, i.e, it has some brothers not yet visited in the right,
    we forbid this node to go back in the hierarchy more than 1 level to continue the search; if it would do that, the
    paths that will be find from those higher levels won't contain his right side brothers
    and this is not logical correct.
    :param is_job: is (j)ump (o)r (b)locking - if in the process of computing the paths the algorithm discovers a jump
    of rounds or a blocking while loop this argument is set to True and is used later in Round Generathing phase to
    wrap the rounds with the required if condition
    :return: nothing. at the end of the algorithm, the paths_list list given as an argument will be filled with tuples
    of (tree, path). is_job will also say if we need a wrapping
    """

    to_delete = []
    ok = True

    if current_node is not None:
        grandparent = current_node
        path.append(grandparent)
        ok = True
        for tupleChild in current_node.children():
            child = tupleChild[1]
            parent = child
            last_if_child_aux = True
            if isinstance(child, If):

                # exploring the tree - there's an if node and we recusively explore it

                check_if_gen = CheckIfGenerator(source_node, dest_node)
                check_if_gen.visit(child.iftrue)

                jump_on_iftrue = check_if_gen.is_jumping
                blocking_on_iftrue = check_if_gen.is_blocking

                jump_on_iffalse = False
                blocking_on_iffalse = False

                if check_if_gen.true_jump or check_if_gen.is_blocking:
                    if not is_job:
                        is_job.append(True)

                check_if_gen.true_jump = False
                check_if_gen.is_jumping = False
                check_if_gen.is_blocking = False

                if child.iffalse is not None:
                    check_if_gen.visit(child.iffalse)
                    jump_on_iffalse = check_if_gen.is_jumping
                    blocking_on_iffalse = check_if_gen.is_blocking

                if check_if_gen.true_jump or check_if_gen.is_blocking:
                    if not is_job:
                        is_job.append(True)

                if not jump_on_iffalse and not jump_on_iftrue \
                        and not blocking_on_iftrue and not blocking_on_iffalse:
                    path.append(child)

                    if last_if is not None:
                        if find_node(last_if, child) is None:
                            last_if.block_items.append(child)
                            to_delete.append(child)
                    continue

                parent_list.append(parent)
                grandparent_list.append(grandparent)
                index = grandparent.block_items.index(parent)
                parent_index.append(index)

                other_children = current_node.block_items[(index + 1):]
                for other_child in other_children:
                    if isinstance(other_child, If):
                        last_if_child_aux = False
                        break

                path1 = path[:]
                path2 = path[:]
                path1.append(parent)
                path2.append(parent)

                pi1 = parent_index[:]
                pi2 = parent_index[:]

                if jump_on_iftrue or blocking_on_iftrue:

                    if child.iffalse is not None:

                        # exploring the tree - jump on iftrue branch and there's an iffalse branch too

                        new_tree_1 = duplicate_element(tree)
                        new_tree_2 = duplicate_element(tree)

                        new_parent_list_1 = []
                        new_grandparent_list_1 = []
                        new_grandparent_list_2 = []
                        new_parent_list_2 = []

                        for parent_node in parent_list:
                            new_parent_list_1.append(find_node(new_tree_1, parent_node))
                            new_parent_list_2.append(find_node(new_tree_2, parent_node))

                        for grandparent_node in grandparent_list:
                            new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))
                            new_grandparent_list_2.append(find_node(new_tree_2, grandparent_node))

                        if last_if is not None:

                            # exploring the three - jump on iftrue and there's an iffalse branch too
                            # last_if is valid

                            last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                            if find_node(last_if_in_new_tree_1, child) is None:
                                last_if_in_new_tree_1.block_items.append(child)
                                to_delete.append(child)

                            child_copy = duplicate_element(child)
                            last_if_in_new_tree_2 = find_node(new_tree_2, last_if)
                            if find_node(last_if_in_new_tree_2, child) is None:
                                last_if_in_new_tree_2.block_items.append(child_copy)
                                if child not in to_delete:
                                    to_delete.append(child)

                            new_grandparent_1 = find_node(new_tree_1, grandparent)
                            new_grandparent_2 = find_node(new_tree_2, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)
                                new_grandparent_2.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1
                                pi2[-1] = pi2[-1] - len(to_delete) + 1

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                last_if_in_new_tree_1, pi1, last_if_child_aux, is_job)

                            find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                new_parent_list_2, new_grandparent_list_2, paths_list,
                                                source_reached, new_tree_2, child_copy.iffalse, pi2,
                                                last_if_child_aux, is_job)

                        else:

                            # exploring the three - jump on iftrue and there's an iffalse branch too
                            # last_if is None

                            new_grandparent_1 = find_node(new_tree_1, grandparent)
                            new_grandparent_2 = find_node(new_tree_2, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)
                                new_grandparent_2.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1
                                pi2[-1] = pi2[-1] - len(to_delete) + 1

                            new_last_if = find_node(new_tree_2, child.iffalse)

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                None, pi1, last_if_child_aux, is_job)

                            find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                new_parent_list_2, new_grandparent_list_2, paths_list,
                                                source_reached, new_tree_2, new_last_if, pi2,
                                                last_if_child_aux, is_job)

                    else:
                        # exploring the three - jump on iftrue and there's no iffalse branch

                        new_tree_1 = duplicate_element(tree)
                        new_parent_list_1 = []
                        new_grandparent_list_1 = []

                        for parent_node in parent_list:
                            new_parent_list_1.append(find_node(new_tree_1, parent_node))

                        for grandparent_node in grandparent_list:
                            new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))

                        if last_if is not None:

                            # exploring the three - jump on iftrue and there's no iffalse branch
                            # last_if is valid

                            last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                            if find_node(last_if_in_new_tree_1, child) is None:
                                last_if_in_new_tree_1.block_items.append(child)
                                to_delete.append(child)

                            new_grandparent_1 = find_node(new_tree_1, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                last_if_in_new_tree_1, pi1, last_if_child_aux, is_job)

                        else:

                            # exploring the three - jump on iftrue there's no iffalse branch
                            # last_if is None

                            new_grandparent_1 = find_node(new_tree_1, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                None, pi1, last_if_child_aux, is_job)

                        new_tree = duplicate_element(tree)
                        new_parent = find_node(new_tree, child)

                        gen = c_generator.CGenerator()
                        condition = ''
                        condition += gen.visit(child.cond)

                        new_parent.cond = ID(condition, child.coord)
                        new_parent.iffalse = Compound([], new_parent.iftrue.coord)
                        new_parent.iftrue = None

                        path.append(new_parent)
                        path.append(new_parent.iffalse)

                        new_parent_list = []
                        new_grandparent_list = []

                        for parent_node in parent_list:
                            new_parent_list.append(find_node(new_tree, parent_node))

                        for grandparent_node in grandparent_list:
                            new_grandparent_list.append(find_node(new_tree, grandparent_node))

                        if last_if is not None:
                            last_if_in_new_tree = find_node(new_tree, last_if)
                            if find_node(last_if_in_new_tree, new_parent) is None:
                                last_if_in_new_tree.block_items.append(new_parent)

                        new_grandparent = find_node(new_tree, grandparent)

                        for node in to_delete:
                            new_grandparent.block_items.remove(node)

                        if len(to_delete) >= 2:
                            pi2[-1] = pi2[-1] - len(to_delete) + 1

                        find_all_paths_util(None, source_node, dest_node, path, new_parent_list,
                                            new_grandparent_list, paths_list, source_reached, new_tree,
                                            new_parent.iffalse, pi2, last_if_child_aux, is_job)

                elif jump_on_iffalse or blocking_on_iffalse:

                    new_tree_1 = duplicate_element(tree)
                    new_tree_2 = duplicate_element(tree)

                    new_parent_list_1 = []
                    new_grandparent_list_1 = []
                    new_grandparent_list_2 = []
                    new_parent_list_2 = []

                    for parent_node in parent_list:
                        new_parent_list_1.append(find_node(new_tree_1, parent_node))
                        new_parent_list_2.append(find_node(new_tree_2, parent_node))

                    for grandparent_node in grandparent_list:
                        new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))
                        new_grandparent_list_2.append(find_node(new_tree_2, grandparent_node))

                    if last_if is not None:
                        # exploring the tree - jump on iffalse branch
                        # last_if is valid

                        child_copy = duplicate_element(child)
                        last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                        if find_node(last_if_in_new_tree_1, child) is None:
                            last_if_in_new_tree_1.block_items.append(child_copy)
                            to_delete.append(child)

                        last_if_in_new_tree_2 = find_node(new_tree_2, last_if)
                        if find_node(last_if_in_new_tree_2, child) is None:
                            last_if_in_new_tree_2.block_items.append(child)
                            if child not in to_delete:
                                to_delete.append(child)

                        new_grandparent_1 = find_node(new_tree_1, grandparent)
                        new_grandparent_2 = find_node(new_tree_2, grandparent)

                        for node in to_delete:
                            new_grandparent_1.block_items.remove(node)
                            new_grandparent_2.block_items.remove(node)

                        if len(to_delete) >= 2:
                            pi1[-1] = pi1[-1] - len(to_delete) + 1
                            pi2[-1] = pi2[-1] - len(to_delete) + 1

                        find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                            new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                            child_copy.iftrue, pi1, last_if_child_aux, is_job)

                        find_all_paths_util(child.iffalse, source_node, dest_node, path2, new_parent_list_2,
                                            new_grandparent_list_2, paths_list, source_reached, new_tree_2,
                                            last_if_in_new_tree_2, pi2, last_if_child_aux, is_job)

                    else:
                        # exploring the tree - jump on iffalse branch
                        # last_if is None

                        new_grandparent_1 = find_node(new_tree_1, grandparent)
                        new_grandparent_2 = find_node(new_tree_2, grandparent)

                        for node in to_delete:
                            new_grandparent_1.block_items.remove(node)
                            new_grandparent_2.block_items.remove(node)

                        if len(to_delete) >= 2:
                            pi1[-1] = pi1[-1] - len(to_delete) + 1
                            pi2[-1] = pi2[-1] - len(to_delete) + 1

                        new_last_if = find_node(new_tree_1, child.iftrue)

                        find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                            new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                            new_last_if, pi1, last_if_child_aux, is_job)

                        find_all_paths_util(child.iffalse, source_node, dest_node, path2, new_parent_list_2,
                                            new_grandparent_list_2, paths_list, source_reached, new_tree_2,
                                            None, pi2, last_if_child_aux, is_job)

                ok = False
                break
            else:

                # exploring the tree - normal node != if node

                path.append(child)

                if last_if is not None:
                    if find_node(last_if, child) is None:
                        last_if.block_items.append(child)
                        to_delete.append(child)

                if child == source_node:
                    source_reached = True

                if child == dest_node:
                    if source_reached is True:
                        paths_list.append((tree, path))
                    ok = False
                    break

        for node in to_delete:
            current_node.block_items.remove(node)

    # back on the ancestors to continue the tree exploration
    if parent_list and grandparent_list and ok is True:
        while grandparent_list:
            to_delete = []
            grandparent = grandparent_list.pop()
            parent = parent_list.pop()
            p_index = parent_index.pop()

            j = 0
            found_parent = False
            for j, tupleChild in enumerate(grandparent.children()):
                if tupleChild[1] == parent:
                    found_parent = True
                    break
            if found_parent:
                remained_children = grandparent.children()[(j + 1):]
            else:
                remained_children = grandparent.children()[p_index:]

            return_after_call = False

            for tupleChild in remained_children:
                child = tupleChild[1]
                parent = child

                last_if_child_aux = True
                if isinstance(child, If):

                    # back on the ancestors - if node left unvisited

                    check_if_gen = CheckIfGenerator(source_node, dest_node)
                    check_if_gen.visit(child.iftrue)

                    jump_on_iftrue = check_if_gen.is_jumping
                    blocking_on_iftrue = check_if_gen.is_blocking

                    if check_if_gen.true_jump or check_if_gen.is_blocking:
                        if not is_job:
                            is_job.append(True)

                    jump_on_iffalse = False
                    blocking_on_iffalse = False

                    check_if_gen.is_jumping = False
                    check_if_gen.is_blocking = False
                    check_if_gen.true_jump = False

                    if child.iffalse is not None:
                        check_if_gen.visit(child.iffalse)
                        jump_on_iffalse = check_if_gen.is_jumping
                        blocking_on_iffalse = check_if_gen.is_blocking

                    if check_if_gen.true_jump or check_if_gen.is_blocking:
                        if not is_job:
                            is_job.append(True)

                    if not jump_on_iffalse and not jump_on_iftrue \
                            and not blocking_on_iftrue and not blocking_on_iffalse:
                        path.append(child)

                        if last_if is not None:
                            if find_node(last_if, child) is None:
                                last_if.block_items.append(child)
                                to_delete.append(child)

                        if remained_children.index(tupleChild) == len(remained_children) - 1:
                            last_if_child = True

                        continue

                    path1 = path[:]
                    path2 = path[:]
                    path1.append(parent)
                    path2.append(parent)

                    index = grandparent.block_items.index(parent)
                    other_children = grandparent.block_items[(index + 1):]
                    for other_child in other_children:
                        if isinstance(other_child, If):
                            last_if_child_aux = False
                            break

                    pl1 = parent_list[:]
                    pl1.append(parent)

                    gp1 = grandparent_list[:]
                    gp1.append(grandparent)

                    pl2 = parent_list[:]
                    pl2.append(parent)

                    gp2 = grandparent_list[:]
                    gp2.append(grandparent)

                    pi1 = parent_index[:]
                    pi1.append(grandparent.block_items.index(parent))

                    pi2 = parent_index[:]
                    pi2.append(grandparent.block_items.index(parent))

                    if jump_on_iftrue or blocking_on_iftrue:

                        if child.iffalse is not None:

                            # exploring the tree - jump on iftrue and there's an iffalse branch

                            new_tree_1 = duplicate_element(tree)
                            new_tree_2 = duplicate_element(tree)

                            new_parent_list_1 = []
                            new_grandparent_list_1 = []
                            new_grandparent_list_2 = []
                            new_parent_list_2 = []

                            for parent_node in pl1:
                                new_parent_list_1.append(find_node(new_tree_1, parent_node))
                                new_parent_list_2.append(find_node(new_tree_2, parent_node))

                            for grandparent_node in gp1:
                                new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))
                                new_grandparent_list_2.append(find_node(new_tree_2, grandparent_node))

                            if last_if is not None:

                                # exploring the tree - jump on iftrue and there's an iffalse branch
                                # last_if is valid

                                last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                                if find_node(last_if_in_new_tree_1, child) is None:
                                    last_if_in_new_tree_1.block_items.append(child)
                                    to_delete.append(child)

                                child_copy = duplicate_element(child)
                                last_if_in_new_tree_2 = find_node(new_tree_2, last_if)
                                if find_node(last_if_in_new_tree_2, child) is None:
                                    last_if_in_new_tree_2.block_items.append(child_copy)
                                    if child not in to_delete:
                                        to_delete.append(child)

                                new_grandparent_1 = find_node(new_tree_1, grandparent)
                                new_grandparent_2 = find_node(new_tree_2, grandparent)

                                for node in to_delete:
                                    new_grandparent_1.block_items.remove(node)
                                    new_grandparent_2.block_items.remove(node)

                                if len(to_delete) >= 2:
                                    pi1[-1] = pi1[-1] - len(to_delete) + 1
                                    pi2[-1] = pi2[-1] - len(to_delete) + 1

                                find_all_paths_util(child.iftrue, source_node, dest_node, path1,
                                                    new_parent_list_1, new_grandparent_list_1, paths_list,
                                                    source_reached, new_tree_1, last_if_in_new_tree_1, pi1,
                                                    last_if_child_aux, is_job)

                                find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                    new_parent_list_2, new_grandparent_list_2, paths_list,
                                                    source_reached, new_tree_2, child_copy.iffalse, pi2,
                                                    last_if_child_aux, is_job)

                            else:

                                # exploring the tree - jump on iftrue and there's an iffalse branch
                                # last_if is None

                                new_grandparent_1 = find_node(new_tree_1, grandparent)
                                new_grandparent_2 = find_node(new_tree_2, grandparent)

                                for node in to_delete:
                                    new_grandparent_1.block_items.remove(node)
                                    new_grandparent_2.block_items.remove(node)

                                if len(to_delete) >= 2:
                                    pi1[-1] = pi1[-1] - len(to_delete) + 1
                                    pi2[-1] = pi2[-1] - len(to_delete) + 1

                                new_last_if = find_node(new_tree_2, child.iffalse)

                                find_all_paths_util(child.iftrue, source_node, dest_node, path1,
                                                    new_parent_list_1, new_grandparent_list_1, paths_list,
                                                    source_reached, new_tree_1, None, pi1, last_if_child_aux,
                                                    is_job)

                                find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                    new_parent_list_2, new_grandparent_list_2, paths_list,
                                                    source_reached, new_tree_2, new_last_if, pi2,
                                                    last_if_child_aux, is_job)

                        else:
                            # exploring the tree - jump on iftrue and there's no iffalse branch

                            new_tree_1 = duplicate_element(tree)
                            new_parent_list_1 = []
                            new_grandparent_list_1 = []

                            for parent_node in pl1:
                                new_parent_list_1.append(find_node(new_tree_1, parent_node))

                            for grandparent_node in gp1:
                                new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))

                            if last_if is not None:

                                # exploring the tree - jump on iftrue and there's no iffalse branch
                                # last_if is valid

                                last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                                if find_node(last_if_in_new_tree_1, child) is None:
                                    last_if_in_new_tree_1.block_items.append(child)
                                    to_delete.append(child)

                                new_grandparent_1 = find_node(new_tree_1, grandparent)

                                for node in to_delete:
                                    new_grandparent_1.block_items.remove(node)

                                if len(to_delete) >= 2:
                                    pi1[-1] = pi1[-1] - len(to_delete) + 1

                                find_all_paths_util(child.iftrue, source_node, dest_node, path1,
                                                    new_parent_list_1, new_grandparent_list_1, paths_list,
                                                    source_reached, new_tree_1, last_if_in_new_tree_1, pi1,
                                                    last_if_child_aux, is_job)

                            else:

                                # exploring the tree - jump on iftrue and there's no iffalse branch
                                # last_if is None

                                new_grandparent_1 = find_node(new_tree_1, grandparent)

                                for node in to_delete:
                                    new_grandparent_1.block_items.remove(node)

                                if len(to_delete) >= 2:
                                    pi1[-1] = pi1[-1] - len(to_delete) + 1

                                find_all_paths_util(child.iftrue, source_node, dest_node, path1,
                                                    new_parent_list_1, new_grandparent_list_1, paths_list,
                                                    source_reached, new_tree_1, None, pi1, last_if_child_aux, is_job)

                            new_tree = duplicate_element(tree)
                            new_parent = find_node(new_tree, child)

                            gen = c_generator.CGenerator()
                            condition = ''
                            condition += gen.visit(child.cond)

                            new_parent.cond = ID(condition, child.coord)
                            new_parent.iffalse = Compound([], new_parent.iftrue.coord)
                            new_parent.iftrue = None

                            path.append(new_parent)
                            path.append(new_parent.iffalse)

                            new_parent_list = []
                            new_grandparent_list = []

                            for parent_node in pl2:
                                new_parent_list.append(find_node(new_tree, parent_node))

                            for grandparent_node in gp2:
                                new_grandparent_list.append(find_node(new_tree, grandparent_node))

                            if last_if is not None:
                                last_if_in_new_tree = find_node(new_tree, last_if)
                                if find_node(last_if_in_new_tree, new_parent) is None:
                                    last_if_in_new_tree.block_items.append(new_parent)

                            new_grandparent = find_node(new_tree, grandparent)

                            for node in to_delete:
                                new_grandparent.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi2[-1] = pi2[-1] - len(to_delete) + 1

                            find_all_paths_util(None, source_node, dest_node, path, new_parent_list,
                                                new_grandparent_list, paths_list, source_reached, new_tree,
                                                new_parent.iffalse, pi2, last_if_child_aux, is_job)

                    elif jump_on_iffalse or blocking_on_iffalse:
                        new_tree_1 = duplicate_element(tree)
                        new_tree_2 = duplicate_element(tree)

                        new_parent_list_1 = []
                        new_grandparent_list_1 = []
                        new_grandparent_list_2 = []
                        new_parent_list_2 = []

                        for parent_node in pl1:
                            new_parent_list_1.append(find_node(new_tree_1, parent_node))
                            new_parent_list_2.append(find_node(new_tree_2, parent_node))

                        for grandparent_node in gp1:
                            new_grandparent_list_1.append(find_node(new_tree_1, grandparent_node))
                            new_grandparent_list_2.append(find_node(new_tree_2, grandparent_node))

                        if last_if is not None:
                            # exploring the tree - jump on iffalse
                            # last_if is valid

                            child_copy = duplicate_element(child)
                            last_if_in_new_tree_1 = find_node(new_tree_1, last_if)
                            if find_node(last_if_in_new_tree_1, child) is None:
                                last_if_in_new_tree_1.block_items.append(child_copy)
                                to_delete.append(child)

                            last_if_in_new_tree_2 = find_node(new_tree_2, last_if)
                            if find_node(last_if_in_new_tree_2, child) is None:
                                last_if_in_new_tree_2.block_items.append(child)
                                if child not in to_delete:
                                    to_delete.append(child)

                            new_grandparent_1 = find_node(new_tree_1, grandparent)
                            new_grandparent_2 = find_node(new_tree_2, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)
                                new_grandparent_2.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1
                                pi2[-1] = pi2[-1] - len(to_delete) + 1

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                child_copy.iftrue, pi1, last_if_child_aux, is_job)

                            find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                new_parent_list_2, new_grandparent_list_2, paths_list,
                                                source_reached, new_tree_2, last_if_in_new_tree_2, pi2,
                                                last_if_child_aux, is_job)

                        else:
                            # exploring the tree - jump on iffalse
                            # last_if is None

                            new_grandparent_1 = find_node(new_tree_1, grandparent)
                            new_grandparent_2 = find_node(new_tree_2, grandparent)

                            for node in to_delete:
                                new_grandparent_1.block_items.remove(node)
                                new_grandparent_2.block_items.remove(node)

                            if len(to_delete) >= 2:
                                pi1[-1] = pi1[-1] - len(to_delete) + 1
                                pi2[-1] = pi2[-1] - len(to_delete) + 1

                            new_last_if = find_node(new_tree_1, child.iftrue)

                            find_all_paths_util(child.iftrue, source_node, dest_node, path1, new_parent_list_1,
                                                new_grandparent_list_1, paths_list, source_reached, new_tree_1,
                                                new_last_if, pi1, last_if_child_aux, is_job)

                            find_all_paths_util(child.iffalse, source_node, dest_node, path2,
                                                new_parent_list_2, new_grandparent_list_2, paths_list,
                                                source_reached, new_tree_2, None, pi2, last_if_child_aux, is_job)

                    return_after_call = True
                    break
                else:

                    # back on the ancestors - normal children are handled on this case, not if nodes

                    path.append(child)

                    if last_if is not None:
                        if find_node(last_if, child) is None:
                            last_if.block_items.append(child)
                            to_delete.append(child)

                    if child == source_node:
                        source_reached = True

                    if child == dest_node:
                        if source_reached is True:
                            paths_list.append((tree, path))
                        break
            for node in to_delete:
                grandparent.block_items.remove(node)

            if last_if_child is False or return_after_call:
                break