Ejemplo n.º 1
0
def ConvertShortCircuitIf(if_stmt: c_ast.If, parent: c_ast.Node, id_gen: common.UniqueId):
    cond = if_stmt.cond
    if isinstance(cond, c_ast.UnaryOp) and cond.op == "!":
        # for a not not just swap the branches
        if_stmt.cond = cond.expr
        if_stmt.iffalse, if_stmt.iftrue = if_stmt.iftrue, if_stmt.iffalse
        ConvertShortCircuitIf(if_stmt, parent, id_gen)
        return

    if not isinstance(cond, c_ast.BinaryOp):
        return

    if cond.op != "&&" and cond.op != "||":
        return

    labelnext = id_gen.next("branch")
    if cond.op == "&&":
        if_stmt2 = c_ast.If(cond.left, c_ast.Goto(labelnext), if_stmt.iffalse)
    else:
        assert cond.op == "||"
        if_stmt2 = c_ast.If(cond.left, if_stmt.iftrue, c_ast.Goto(labelnext))
    if_stmt.cond = cond.right

    stmts = common.GetStatementList(parent)
    # this is easy to fix but basically guaranteed after running IfTransform
    assert stmts, parent
    pos = stmts.index(if_stmt)
    stmts[pos:pos + 1] = [if_stmt2, c_ast.Label(labelnext, c_ast.EmptyStatement()), if_stmt]
    ConvertShortCircuitIf(if_stmt2, parent, id_gen)
    ConvertShortCircuitIf(if_stmt, parent, id_gen)
Ejemplo n.º 2
0
def ConvertWhileLoop(ast, id_gen: common.UniqueId):
    def IsWhileLoop(node, _):
        return isinstance(node, (c_ast.DoWhile, c_ast.While))

    candidates = common.FindMatchingNodesPostOrder(ast, ast, IsWhileLoop)
    for node, parent in candidates:
        loop_label = id_gen.next("while")
        test_label = loop_label + "_cond"
        exit_label = loop_label + "_exit"
        conditional = c_ast.If(node.cond, c_ast.Goto(loop_label), None)
        block = [c_ast.Label(loop_label, c_ast.EmptyStatement()), node.stmt,
                 c_ast.Label(test_label, c_ast.EmptyStatement()), conditional,
                 c_ast.Label(exit_label, c_ast.EmptyStatement())]
        if isinstance(node, c_ast.While):
            block = [c_ast.Goto(test_label)] + block
        common.ReplaceBreakAndContinue(node.stmt, node, test_label, exit_label)
        common.ReplaceNode(parent, node, c_ast.Compound(block))
Ejemplo n.º 3
0
def ConvertForLoop(ast, id_gen: common.UniqueId):
    candidates = common.FindMatchingNodesPostOrder(
        ast, ast, lambda n, _: isinstance(n, c_ast.For))
    for node, parent in candidates:
        loop_label = id_gen.next("for")
        next_label = loop_label + "_next"
        test_label = loop_label + "_cond"
        exit_label = loop_label + "_exit"
        goto = c_ast.Goto(loop_label)
        conditional = c_ast.If(node.cond, goto, None) if node.cond else goto
        block = ExtractForInitStatements(node.init) + [
            c_ast.Goto(test_label),
            c_ast.Label(loop_label, c_ast.EmptyStatement()), node.stmt,
            c_ast.Label(next_label, c_ast.EmptyStatement()),
            node.next if node.next else c_ast.EmptyStatement(),
            c_ast.Label(test_label, c_ast.EmptyStatement()), conditional,
            c_ast.Label(exit_label, c_ast.EmptyStatement())
        ]
        common.ReplaceBreakAndContinue(node.stmt, node, next_label, exit_label)
        common.ReplaceNode(parent, node, c_ast.Compound(block))
Ejemplo n.º 4
0
def ConvertToGotos(if_stmt: c_ast.If, parent, id_gen: common.UniqueId):
    if (isinstance(if_stmt.iftrue, c_ast.Goto) and
            isinstance(if_stmt.iffalse, c_ast.Goto) and
            not isinstance(if_stmt.cond, c_ast.ExprList)):
        return

    label = id_gen.next("if")
    labeltrue = label + "_true"
    labelfalse = label + "_false"
    labelend = label + "_end"
    emptytrue = common.IsEmpty(if_stmt.iftrue) or isinstance(if_stmt.iftrue, c_ast.Goto)
    emptyfalse = common.IsEmpty(if_stmt.iffalse) or isinstance(if_stmt.iffalse, c_ast.Goto)

    seq: List[c_ast.Node] = []
    # TODO: this should be done in  EliminateExpressionLists(
    if isinstance(if_stmt.cond, c_ast.ExprList):
        exprs = if_stmt.cond.exprs
        if_stmt.cond = exprs.pop(-1)
        seq += exprs
    seq.append(if_stmt)
    if not emptytrue:
        seq += [c_ast.Label(labeltrue, c_ast.EmptyStatement()), if_stmt.iftrue]
        if not emptyfalse:
            seq.append(c_ast.Goto(labelend))
    if not emptyfalse:
        seq += [c_ast.Label(labelfalse, c_ast.EmptyStatement()), if_stmt.iffalse]
    seq.append(c_ast.Label(labelend, c_ast.EmptyStatement()))

    if not isinstance(if_stmt.iftrue, c_ast.Goto):
        if_stmt.iftrue = c_ast.Goto(labelend if emptytrue else labeltrue)
    if not isinstance(if_stmt.iffalse, c_ast.Goto):
        if_stmt.iffalse = c_ast.Goto(labelend if emptyfalse else labelfalse)

    stmts = common.GetStatementList(parent)
    if not stmts:
        stmts = [if_stmt]
        parent = common.ReplaceNode(parent, if_stmt, c_ast.Compound(stmts))

    pos = stmts.index(if_stmt)
    stmts[pos: pos + 1] = seq
Ejemplo n.º 5
0
def ReplaceBreakAndContinue(node, parent, test_label, exit_label):
    """ Starting at `node` recursively replace
    all `continue` statements with `goto test_label` and
    all `break` statements with `goto exit_label`
    """
    if isinstance(node, c_ast.Continue):
        ReplaceNode(parent, node, c_ast.Goto(test_label))
        return
    if exit_label and isinstance(node, c_ast.Break):
        ReplaceNode(parent, node, c_ast.Goto(exit_label))
        return

    if isinstance(node, (c_ast.While, c_ast.DoWhile, c_ast.For)):
        # do not recurse into other loops
        return

    if isinstance(node, c_ast.Switch):
        # `break`s inside switches have their own meaning but we still need to replace `continue`s
        exit_label = None

    for c in node:
        ReplaceBreakAndContinue(c, node, test_label, exit_label)
Ejemplo n.º 6
0
 def generic_visit(self, node):
     for ci, (c_name, c) in enumerate(node.children()):
         self.visit(c)
         # If child is sliced, then mark this as well
         if c.sliced:
             node.sliced = True
             # If adding an assignment, ensure that it is declared by adding lvalue
             # to dependency list
             # FIXME: Only need to declare this variable, not handle all its dependences
             if isinstance(node, c_ast.Assignment):
                 self.id_visitor.new_visit(node.lvalue)
                 self.rvalues += self.id_visitor.IDs
             """
     print "Adding to slice:"
     print_node(node)
     print "because child is in slice:"
     print_node(c)
     print
     """
         # Always include Returns, change them to Goto end of function
         if isinstance(c, c_ast.Return):
             # Create a new compound node
             insert_node = c_ast.Compound([])
             """
     # If there is a return value, add statement for return_value = value
     if c.expr:
       ret_id = c_ast.ID("return_value")
       ret_id.sliced = True
       assignment = c_ast.Assignment("=", ret_id, c.expr)
       assignment.sliced = True
       insert_node.block_items.append(assignment)
     """
             # Goto end of function
             goto = c_ast.Goto(self.end_label)
             goto.sliced = True
             insert_node.block_items.append(goto)
             insert_node.sliced = True
             # Add compound node back to function
             if isinstance(node, c_ast.Compound):
                 node.block_items[ci] = insert_node
             elif isinstance(node, c_ast.If):
                 exec("node.%s = insert_node" % c_name)
             elif isinstance(node, c_ast.Case):
                 node.stmts[ci - 1] = insert_node
             else:
                 print_node(node)
                 node.show(nodenames=True, showcoord=True)
                 raise Exception(
                     "Unsupported parent node type %s. Please implement." %
                     (type(node)))
Ejemplo n.º 7
0
 def generic_visit(self, node):
   for ci, (c_name, c) in enumerate(node.children()):
     # Return statement
     if isinstance(c, c_ast.Return):
       # Create a new compound node
       insert_node = c_ast.Compound([])
       # If there is a return value, add statement for return_value = value
       if c.expr:
         insert_node.block_items.append(c_ast.Assignment("=", c_ast.ID("return_value"), c.expr))
       # Add goto to end of function block
       insert_node.block_items.append(c_ast.Goto(self.goto_name))
       # Replace original node with new node
       replace_node(node, insert_node, ci, c_name)
     # Non-return statement, continue visiting
     else:
       self.visit(c)
Ejemplo n.º 8
0
def do_jump(**kw):
    #goto {loc}
    # fmt_op returns an ID but Goto takes a bare string
    return c_ast.Goto(kw['loc'].name)