def visit_FuncDef(self, node):
    # Skip if no loop counters exist
    if self.loop_counter_size == 0:
      return

    # Create loop_counter declaration/initialization
    constants = [c_ast.Constant("int", '0') for i in range(self.loop_counter_size)]
    init_list = c_ast.InitList(constants)
    identifier_type = c_ast.IdentifierType(["int"])
    type_decl = c_ast.TypeDecl("loop_counter", [], identifier_type)
    dim = c_ast.Constant("int", str(self.loop_counter_size))
    array_decl = c_ast.ArrayDecl(type_decl, dim, [])
    decl = c_ast.Decl("loop_counter", [], [], [], array_decl, init_list, None) 
    node.body.block_items.insert(0, decl)

    # Label for return values to goto
    start_label = c_ast.Label("print_loop_counter", c_ast.EmptyStatement())
    # Start and end labels used for inserting preprocessor commands for #if DEBUG_EN
    end_label = c_ast.Label("print_loop_counter_end", c_ast.EmptyStatement())

    # Write to file
    if self.write_to_file:
      stmt = c_ast.ID("write_array(loop_counter, %d)\n" % (self.loop_counter_size))
      compound = c_ast.Compound([start_label, stmt, end_label])
    # Print to stdout
    else:
      # Add printf to the end of function
      # Start of printing
      stmt_start = c_ast.ID("printf(\"loop counter = (\")")

      # For loop
      # int i;
      identifier_type = c_ast.IdentifierType(["int"])
      type_decl = c_ast.TypeDecl("i", [], identifier_type)
      for_decl = c_ast.Decl("i", [], [], [], type_decl, [], None)
      # i = 0
      init = c_ast.Assignment("=", c_ast.ID("i"), c_ast.Constant("int", '0'))
      # i < self.loop_counter_size
      cond = c_ast.BinaryOp("<", c_ast.ID("i"), c_ast.Constant("int", str(self.loop_counter_size)))
      # i++
      next_stmt = c_ast.UnaryOp("p++", c_ast.ID("i"))
      # printf in for
      stmt = c_ast.ID("printf(\"%d, \", loop_counter[i])")
      # Cosntruct for loop
      stmt_for = c_ast.For(init, cond, next_stmt, stmt)

      # End of printing
      stmt_end = c_ast.ID("printf(\")\\n\")")
      
      # Put it all together
      body = c_ast.Compound([stmt_start, for_decl, stmt_for, stmt_end])
      # Surround with labels
      compound = c_ast.Compound([start_label, body, end_label])
    node.body.block_items.append(compound)
Ejemplo n.º 2
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.º 3
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))
 def visit_FuncDef(self, node):
   label = c_ast.Label("predict_exec_time", c_ast.EmptyStatement())
   decl = c_ast.Decl("exec_time", None, None, None,
       c_ast.TypeDecl("exec_time", None, c_ast.IdentifierType(["float"])), 
       None, None)
   assignment = c_ast.Assignment('=', c_ast.ID("exec_time"), c_ast.Constant("int", 0))
   ret = c_ast.Return(c_ast.ID("exec_time"))
   compound = c_ast.Compound([label, decl, assignment, ret])
   node.body.block_items.append(compound)
Ejemplo n.º 5
0
 def callback(expr: ca.Node, is_expr: bool) -> Optional[ca.Node]:
     if indices[expr] in repl_cands_set:
         return copy.deepcopy(repl_expr)
     if expr == write and isinstance(write, ca.Assignment) and not keep_var:
         if is_expr:
             return write.lvalue
         else:
             return ca.EmptyStatement()
     return None
Ejemplo n.º 6
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.º 7
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.º 8
0
 def generic_visit(self, node):
     #print(node.coord)
     if (isinstance(node, c_ast.If)):
         if (node.iftrue and not (isinstance(node.iftrue, c_ast.Compound))):
             node.iftrue = c_ast.Compound([node.iftrue])
         if (node.iffalse
                 and not (isinstance(node.iffalse, c_ast.Compound))):
             node.iffalse = c_ast.Compound([node.iffalse])
         elif (node.iffalse == None):
             node.iffalse = c_ast.Compound([c_ast.EmptyStatement()])
     elif (isinstance(node, c_ast.For)):
         if (node.stmt and not (isinstance(node.stmt, c_ast.Compound))):
             node.stmt = c_ast.Compound([node.stmt])
     for c_name, c in node.children():
         self.visit(c)
Ejemplo n.º 9
0
    def _pt_trash(self, node):
        if self._rounds == 0:
            return c_ast.EmptyStatement()

        filename = random.choice(random.choice(self._patterns))
        with open(filename) as f:
            ast = self._parser.parse(f.read())

        code = None
        for child in ast.ext:
            if type(child) == c_ast.FuncDef and child.decl.name == 'pattern':
                code = child.body
                pattern = PatternVisitor(self._patterns, self._rounds - 1,
                                         node)
                pattern.visit(code)
                self._pt_add_decls(pattern.decls)
            elif type(child) == c_ast.Decl and type(
                    child.type) == c_ast.FuncDecl:
                self._pt_add_decls([child])
        assert code, 'Invalid pattern: {}'.format(filename)
        return code
Ejemplo n.º 10
0
def generate_code(request, response):
    for proto_file in request.proto_file:
        output = []

        ast = c_ast.FileAST([])
        generator = c_generator.CGenerator()

        ast.ext += [c_ast.EmptyStatement()]

        # Parse request
        for item, package in traverse(proto_file):
            data = {
                'package': proto_file.package or '&lt;root&gt;',
                'filename': proto_file.name,
                'name': item.name,
            }

            if isinstance(item, DescriptorProto):
                data.update({
                    'type': 'Message',
                    'properties': [{'name': f.name, 'type': int(f.type)}
                                   for f in item.field]
                })

            elif isinstance(item, EnumDescriptorProto):
                data.update({
                    'type': 'Enum',
                    'values': [{'name': v.name, 'value': v.number}
                               for v in item.value]
                })

            output.append(data)

        # Fill response
        f = response.file.add()
        f.name = proto_file.name + '.c'
        f.content = generator.visit(ast)
Ejemplo n.º 11
0
 def _pt_assign_choise(self, node):
     return c_ast.EmptyStatement()
Ejemplo n.º 12
0
def do_nop(**kw):
    return c_ast.EmptyStatement()
Ejemplo n.º 13
0
 def __init__(self):
     astnode = c_ast.EmptyStatement()
     super().__init__(astnode)
Ejemplo n.º 14
0
    def ast_to_cfg(self, ast: c_ast.Node) -> (c_ast.Node, c_ast.Node):
        """Recursively compute the CFG from a AST. Given a AST node (can be any 
        complex structure) the function will return the first and last nodes of the
        CFG in a tuple and will modify `cfg` adding the corresponding nodes and 
        edges representing the final CFG.

        Parameters
        ----------
        ast : pycparser.c_ast.Node to be translated into a CFG
        
        Returns
        -------
        A tuple with references to the first and last element of the CFG
        """
        typ = type(ast) 

        entrynode = ControlFlowGraph.EntryNode()
        exitnode = ControlFlowGraph.ExitNode()
        
        self.add_node(entrynode)
        self.add_node(exitnode)

        # A c_ast.If in CFG is:
        #              cfg(body.true)
        #         /                      \
        # if(cond)                       endif*
        #         \                      /
        #          ----------------------
        #
        # returns (if(c), endif)

        if typ == c_ast.If:
            
            astif = c_ast.If(ast.cond, None, None, coord=ast.coord)
            if_start = ControlFlowGraph.IfNode(astif)

            self.add_node(if_start)

            self.add_edge(entrynode, if_start)

            true_branch_body_entry, true_branch_body_exit = self.ast_to_cfg(ast.iftrue)

            asserttrue = ControlFlowGraph.AssertNode(ast.cond)
            self.add_node(asserttrue)
            self.add_edge(if_start, asserttrue)
            self.add_edge(asserttrue, true_branch_body_entry)
            
            self.join_adjacents_and_merge(asserttrue, removed_node=true_branch_body_entry) 
            self.join_adjacents_and_merge(exitnode, removed_node=true_branch_body_exit)  

            if ast.iffalse is not None:
                false_branch_body_start, false_branch_body_last = self.ast_to_cfg(ast.iffalse)

                if self.iffalse:
                    assertfalse = ControlFlowGraph.AssertNode(c_ast.UnaryOp("!", ast.cond))
                    self.add_node(assertfalse)
                    self.add_edge(if_start, assertfalse)
                    self.add_edge(assertfalse, false_branch_body_start)
                else:
                    self.add_edge(if_start, false_branch_body_start)

                self.join_adjacents_and_merge(assertfalse, removed_node=false_branch_body_start) 
                self.join_adjacents_and_merge(exitnode, removed_node=false_branch_body_last) 
            else:
                if self.iffalse:
                    assertfalse = ControlFlowGraph.AssertNode(c_ast.UnaryOp("!", ast.cond))
                    self.add_node(assertfalse)
                    self.add_edge(if_start, assertfalse)
                    self.add_edge(assertfalse, exitnode)
                else:
                    self.add_edge(if_start, exitnode)

        # A c_ast.While in CFG is:
        #           cfg(body)
        #          /         \
        # while(c)            endwhile* -->--+
        #       ^  \         /               |
        #       |   ---->----                |
        #       +----------------------------+
        #
        # returns (while(c), endwhile*)
        
        elif typ == c_ast.While:

            while_body_entry, while_body_exit = self.ast_to_cfg(ast.stmt)
            
            astwhile = c_ast.While(ast.cond, None, coord=ast.coord)
            whilenode = ControlFlowGraph.Node(astwhile)
            self.add_node(whilenode)
            
            self.add_edge(whilenode, exitnode)
            self.add_edge(entrynode, whilenode)

            asserttrue = ControlFlowGraph.AssertNode(ast.cond)
            self.add_node(asserttrue)
            self.add_edge(whilenode, asserttrue)
            self.add_edge(asserttrue, while_body_entry)

            self.join_adjacents_and_merge(asserttrue, removed_node=while_body_entry) 
            # In a while the last statement return to the while condition
            if self.loop:
                self.join_adjacents_and_merge(whilenode, removed_node=while_body_exit) 
            else:
                self.join_adjacents_and_merge(exitnode, removed_node=while_body_exit)


        # A c_ast.Compound in CFG is:
        #
        # cfg(block(1)) --> cfg(block(2)) --> ... --> cfg(block(n))
        #
        # return (cfg(block(1)).first, cfg(block(n)).last)

        elif typ == c_ast.Compound:

            items = ast.block_items

            if items is not None:

                first_node = items[0]
                
                first_node_entry, prev_node_exit = self.ast_to_cfg(first_node)

                self.join_adjacents_and_merge(entrynode, removed_node=first_node_entry) 

                if len(items) > 1:
    
                    for i in items[1:-1]:
                        i_node_entry, i_node_exit = self.ast_to_cfg(i)
                        
                        self.join_adjacents_and_remove(prev_node_exit, i_node_entry)
                        
                        prev_node_exit = i_node_exit
                    
                    last_node = items[-1]

                    last_node_entry, last_node_exit = self.ast_to_cfg(last_node)

                    self.join_adjacents_and_remove(prev_node_exit, last_node_entry)

                else:
                    last_node = first_node
                    last_node_exit = prev_node_exit

                self.join_adjacents_and_merge(exitnode, removed_node=last_node_exit) 
                

            else:
                noopnode = ControlFlowGraph.Node(c_ast.EmptyStatement(coord=ast.coord))
                self.add_node(noopnode)

                self.add_edge(entrynode, noopnode)
                self.add_edge(noopnode, exitnode)


        # A c_ast.Compound in CFG is:
        #
        # function.name --> cfg(function.body).first
        #
        # return (function.name, cfg(function.body).last)

        elif typ == c_ast.FuncDef:

            (first_body, last_body) = self.ast_to_cfg(ast.body)

            astfuncdef = c_ast.FuncDef(ast.decl, ast.param_decls, None, coord=ast.coord)
            funcdefnode = ControlFlowGraph.Node(astfuncdef)

            self.add_node(funcdefnode)

            self.add_edge(entrynode, funcdefnode)
            self.add_edge(last_body, exitnode)

            # we insert the FuncDef body CFG discarding its entry and exit nodes
            self.join_adjacents_and_merge(funcdefnode, removed_node=first_body) 
            self.join_adjacents_and_merge(exitnode, removed_node=last_body)

        else:
            basicnode = ControlFlowGraph.Node(ast)
            self.add_node(basicnode)

            self.add_edge(entrynode, basicnode)
            self.add_edge(basicnode, exitnode)


        return entrynode, exitnode   
        
Ejemplo n.º 15
0
  def create_inline_function(self, function, caller):
    """
    Create a modified version of the passed function that can be inlined.
    """
    # Create a copy of the function
    function_copy = copy.deepcopy(function)

    # Find all declared variables and rename them to prevent aliasing with upper-level
    self.decl_visitor = GetDeclVisitor()
    self.decl_visitor.visit(function_copy.body)
    for decl in self.decl_visitor.decls:
      self.rename_visitor.new_visit(decl, decl + "_rename%d" % self.rename_counter, function_copy)

    ###################################
    # Function Arguments
    ###################################
    function_copy.body.block_items.insert(0, c_ast.ID("// End of arguments"))
    args = []
    ptr_args = []
    # If it has arguments
    if function_copy.decl.type.args:
      # For each function argument and passed value
      for (arg, init) in zip(function_copy.decl.type.args.params, caller.args.exprs):
        # Pointers just get renamed, no re-declare
        if isinstance(arg.type, c_ast.PtrDecl):
          # Add pointer name to list
          if isinstance(init, c_ast.UnaryOp):
            ptr_args.append((self.get_Decl_name(arg), init.expr.name))
          elif isinstance(init, c_ast.StructRef):
            ptr_args.append((self.get_Decl_name(arg), self.cgenerator.visit(init)))
          elif isinstance(init, c_ast.ID):
            ptr_args.append((self.get_Decl_name(arg), init.name))
          elif isinstance(init, c_ast.ArrayRef):
            ptr_args.append((self.get_Decl_name(arg), init))
          else: 
            raise Exception("Unsupported init type %s" % (type(init)))
        # Arrays also get renamed, no re-declare
        elif isinstance(arg.type, c_ast.ArrayDecl):
          ptr_args.append((self.get_Decl_name(arg), init))
        else:
          # Assign passed value to argument declaration
          arg.init = init
          # Save list of argument name for renaming
          arg_name = self.get_Decl_name(arg)
          args.append(arg_name)
          # Rename arguments to prevent aliasing with upper-level
          self.rename_visitor.new_visit(arg_name, arg_name + "_rename%d" % self.rename_counter, function_copy.body)
          self.set_Decl_name(arg, arg_name + "_rename%d" % self.rename_counter)
          # Insert into start of function
          function_copy.body.block_items.insert(0, arg)

    # Rename pointers and arrays to the passed variable
    for arg in ptr_args:
      self.rename_visitor.new_visit(arg[0], arg[1], function_copy)
    # Increment rename counter to ensure unique names
    self.rename_counter += 1

    # Add declaration for return value (if function is non-void)
    if self.get_Function_type(function_copy) != "void":
      # Copy the function type declaration
      typedecl = copy.deepcopy(function.decl.type.type)
      # Create a variable declaration using the function type
      decl = c_ast.Decl(None, None, None, None, typedecl, None, None)
      # Replace the variable name as return_value
      self.set_Decl_name(decl, "return_value")
      # Insert the return_value declaration at the start of the function
      function_copy.body.block_items.insert(0, decl)
    function_copy.body.block_items.insert(0, c_ast.ID("// Inline function: %s" % (function_copy.decl.name)))

    ###################################
    # Return statements
    ###################################
    # Replace returns with goto statement
    return_label = "return%d" % (self.return_counter)
    self.return_counter += 1
    self.rtg_visitor.new_visit(return_label, function_copy)
    # Create label for goto
    function_copy.body.block_items.append(c_ast.Label(return_label, c_ast.EmptyStatement()))

    return function_copy
Ejemplo n.º 16
0
  # Generate AST
  ast = parse_file(filename, use_cpp=True)

  # Find all defined functions
  v = GetFunctionsVisitor()
  v.visit(ast)
  functions = v.funcs

  # Remove function calls from being embedded in conditionals
  v = GetFuncDeclVisitor()
  v.visit(ast)
  v = RemoveIfFunctionVisitor(v.func_decls)
  v.visit(ast)
  # Inline functions
  v = ExpandFunctionVisitor(top_func, functions)
  v.visit(ast)
  # Keep performing until no changes
  while v.expanded:
    v.expanded = False
    v.visit(ast)

  # Print out non-function top-levels
  for c_name, c in ast.children():
    if not isinstance(c, c_ast.FuncDef):
      print_node(c) 
      print_node(c_ast.EmptyStatement())
  # Print out top-level function
  for function in functions:
    if function.decl.name == top_func:
      print_node(function)