def convert(node): loop_node = node.loop_node parent_index = node.parent[1] # index in the AST of the original loop node.parent[0].block_items.pop( parent_index) # remove the original loop from AST body = [] # list of new AST nodes for each peel original_body = [] if loop_node.stmt.block_items is not None: original_body = loop_node.stmt.block_items if isinstance(loop_node, c_ast.For): if loop_node.init is not None: body.append( loop_node.init.decls[0] ) # add the initialization of the loop var before the loop if loop_node.next is not None: loop_node.stmt = c_ast.Compound( original_body + [loop_node.next ]) # add the inc/dec of the loop var at the end of the body body.append(c_ast.While(loop_node.cond, loop_node.stmt)) if isinstance( loop_node, c_ast.DoWhile ): # if loop is a DoWhile, add the commands of the first peel outside of the loop for i in original_body: # add each command to the modified AST body.append(i) body.append(c_ast.While(loop_node.cond, c_ast.Compound(original_body))) for i in body: # add new nodes to the modified AST node.parent[0].block_items.insert(parent_index, i) parent_index = parent_index + 1 node.parent = (node.parent[0], parent_index - 1) # update the parent
def from_code(self, code: str, parser=None): """ Takes (partial) C code as a string and returns the AST node that belongs to it. Wraps everything in a block. Note: This function may not understand all code strings and shall be used with care. But, it understands everything that is either directly valid C code, or partial code that can be put into a function body or as a condition block (e.g. if and while conditions). :param code: The C code. :param parser: If you have already created a parser, you can hint it here. No need to create multiple parsers. :return: The corresponding AST compound. :rtype: c_ast.Compound or None """ # TODO this is a bit hacky, trying to wrap the code s.t. it is hopefully valid to allow for partial parsing. if not parser: parser = GnuCParser() try: ast = parser.parse(code) return c_ast.Compound(ast.ext) except: try: wrapped_code = "void f() { " + code + " }" ast = parser.parse(wrapped_code) return ast.ext[0].body except: try: wrapped_code = "void f() { if(" + code + ") {} }" ast = parser.parse(wrapped_code) return c_ast.Compound( [ast.ext[0].body.block_items[0].cond]) except Exception as e: print(e) return None
def realProcess(self, astNode): typ = type(astNode) def checkCompound(node): """ 检查一个节点是否是大括号的语句块 """ return node and not isinstance(node, c_ast.Compound) # if 语句 if typ == c_ast.If: if checkCompound(astNode.iftrue): newCompound = c_ast.Compound([astNode.iftrue]) astNode.iftrue = newCompound if checkCompound(astNode.iffalse): newFCompound = c_ast.Compound([astNode.iffalse]) astNode.iffalse = newFCompound # For if typ == c_ast.For: if checkCompound(astNode.stmt): newCompound = c_ast.Compound([astNode.stmt]) astNode.stmt = newCompound # While if typ == c_ast.While: if checkCompound(astNode.stmt): newCompound = c_ast.Compound([astNode.stmt]) astNode.stmt = newCompound
def optimize_new(graph, tabDeg, myWhile): maxdeg = max_deg_of_list(tabDeg) while_node = myWhile.node_while peeling_deg = maxdeg + 1 if peeling_deg == 0: myWhile.isOpt = True return 0 initial_indices = [] tabDegs = [] nodelists = [] listIf = [] for i in range(peeling_deg): nodelists.append([]) tabDegs.append([]) initial_indices.append([]) for i in range(len(tabDeg)): for j in range(len(initial_indices)): initial_indices[j].append(i) for deg in tabDeg: for i in range(len(tabDegs)): tabDegs[i].append(deg) for node in while_node.stmt.block_items: for i in range(peeling_deg): nodelists[i].append(node) for i in range(maxdeg): tbrm = [] for init_ind in initial_indices[i]: if init_ind != -1: if tabDeg[init_ind] == i + 1: tbrm.append(init_ind) for init_ind in tbrm: curr_ind = initial_indices[i].index(init_ind) (capture_tab, recover_tab) = captures(init_ind, myWhile.node_while, tabDeg, graph) for capture in capture_tab: if capture[1] == -1 or capture[1] > i + 1: for k in range(len(capture[0])): nodelists[i].insert(curr_ind + 1, capture[0][k]) initial_indices[i].insert(curr_ind + 1, -1) for j in range(i + 1, peeling_deg): curr_ind = initial_indices[j].index(init_ind) for (recover, deg) in recover_tab: if deg == -1 or deg > j: nodelists[j].insert(curr_ind + 1, recover) initial_indices[j].insert(curr_ind + 1, -1) nodelists[j].pop(curr_ind) initial_indices[j].pop(curr_ind) if DEBUG_LEVEL >= 3: print(maxdeg, nodelists, initial_indices) listIf.append( c_ast.If(while_node.cond, c_ast.Compound(nodelists[i]), None)) listIf.append( c_ast.While(while_node.cond, c_ast.Compound(nodelists[maxdeg]), None)) myWhile.parent[0].block_items.pop(myWhile.parent[1]) listIf.reverse() for node in listIf: myWhile.parent[0].block_items.insert(myWhile.parent[1], node) myWhile.show() myWhile.isOpt = True
def merge_libs_calls(self, node): start = -1 end = -1 argumented_client = None argumented_lib = None LibCV = LibCallHunter(self.lib_name) if isinstance(node, c_ast.If): if isinstance(node.iftrue, c_ast.Compound): checking_blocks = node.iftrue.block_items elif isinstance(node, c_ast.FuncDef): checking_blocks = node.body.block_items elif isinstance(node, c_ast.Compound): checking_blocks = node.block_items else: checking_blocks = [] new_leaf = set() mulitiple_call = False for index in range(len(checking_blocks)): LibCV.use_lib = False block = checking_blocks[index] LibCV.visit(block) if LibCV.use_lib: for lib in LibCV.lib_node: l_object = self.node_dict.get(lib, None) if l_object is None: l_object, _ = self.create_ClientContextNode( lib, lib, None, lib, None) self.node_dict[node] = l_object new_leaf.add(l_object) if (start == -1): start = index if (end < index): end = index if (len(LibCV.lib_node) > 1): mulitiple_call = True if (end > start) or (start == end and mulitiple_call): argumented_lib = c_ast.Compound( block_items=checking_blocks[start:end + 1]) argumented_client = copy.deepcopy(node) if isinstance(argumented_client, c_ast.If): if isinstance(argumented_client.iftrue, c_ast.Compound): blocks = argumented_client.iftrue.block_items argumented_client.iftrue.block_items = blocks[:start] + [ c_ast.FuncCall(name=c_ast.ID(name="CLEVER_DELETE"), args=None) ] + blocks[end + 1:] elif isinstance(argumented_client, c_ast.FuncDef): blocks = argumented_client.body.block_items argumented_client.body.block_items = blocks[:start] + [ c_ast.Compound(block_items=[ c_ast.FuncCall(name=c_ast.ID(name="CLEVER_DELETE"), args=None) ] + checking_blocks[start:end + 1]) ] + blocks[end + 1:] return start, end, argumented_lib, argumented_client, new_leaf
def visit_If(self, node): if type(node.iftrue) is not c_ast.Compound: node.iftrue = c_ast.Compound([node.iftrue]) if type(node.iffalse) is not c_ast.Compound: node.iffalse = c_ast.Compound([node.iffalse]) self.generic_visit(node.iftrue) self.generic_visit(node.iffalse)
def visit_If(self, node): if node.iftrue is not None and not isinstance(node.iftrue, c_ast.Compound): node.iftrue = c_ast.Compound([node.iftrue]) if node.iffalse is not None and not isinstance(node.iffalse, c_ast.Compound): node.iffalse = c_ast.Compound([node.iffalse]) self.generic_visit(node)
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)
def insertTest(self, block, functionName, varVals, varTypes, timer, preOut, testId): #Fork call cFork = c_ast.Assignment(lvalue=c_ast.ID(name='child_pid'), op='=', rvalue=c_ast.FuncCall(c_ast.ID(name='fork'), args=None)) #Child ##stdout = freopen("out.txt", "w", stdout); fileOut = c_ast.Constant(type="char", value='"' + preOut + '.' + testId + ".out.txt" + '"') fileW = c_ast.Constant(type="char", value='"' + "w" + '"') fileStdout = c_ast.ID(name='stdout') expressList = [fileOut, fileW, fileStdout] freopenC = c_ast.FuncCall(c_ast.ID(name="freopen"), c_ast.ExprList(expressList)) outReassign = c_ast.Assignment(lvalue=fileStdout, op='=', rvalue=freopenC) ##mainfake() expressList = list( c_ast.Constant(type=varTypes[i], value=str(varVals[i])) for i in range(len(varVals))) funcCall = c_ast.FuncCall(c_ast.ID(name=functionName), c_ast.ExprList(expressList)) funcCall = c_ast.FuncCall(c_ast.ID(name=functionName), c_ast.ExprList(expressList)) ##exit(0) funcCall2 = c_ast.FuncCall( c_ast.ID(name="exit"), c_ast.ExprList([c_ast.Constant(type='int', value='0')])) #Parent cAlarm = c_ast.FuncCall( c_ast.ID(name='alarm'), c_ast.ExprList([c_ast.Constant(type='int', value=str(timer))])) cWait = c_ast.FuncCall(c_ast.ID(name='wait'), c_ast.ExprList([c_ast.ID(name='0')])) #IFs if_false = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='child_pid'), op='==', right=c_ast.Constant(type='int', value='0')), c_ast.Compound([outReassign, funcCall, funcCall2]), iffalse=None) if_ini = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='child_pid'), op='>', right=c_ast.Constant(type='int', value='0')), c_ast.Compound([cAlarm, cWait]), iffalse=if_false) block.body.block_items.insert(1, if_ini) block.body.block_items.insert(1, cFork)
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 (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)
def visit_Assignment(self, node): if self.inner_for: self.remove_node() if self.begin: if not self.inner_begin_block: self.inner_begin_block = c_ast.Compound([]) code = c_ast.If(c_ast.BinaryOp("==", self.inner_index, c_ast.Constant('int', '0')), self.inner_begin_block, None) self.inner_for.stmt.block_items.insert(0, code) self.inner_begin_block.block_items.append(node) else: if not self.inner_end_block: self.inner_end_block = c_ast.Compound([]) code = c_ast.If(c_ast.BinaryOp("==", self.inner_index, c_ast.BinaryOp('-', self.inner_limit, c_ast.Constant('int', '1'))), self.inner_end_block, None) self.inner_for.stmt.block_items.append(code) self.inner_end_block.block_items.append(node)
def merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, mode): ext_after = [] block_items_after = [] block_items_before = [] ext_before = ast_tree.ext[:ext_index] if (len(ast_tree.ext) > 1): ext_after = ast_tree.ext[ext_index + 1:] func_def_decl = ast_tree.ext[ext_index].decl para_decl = ast_tree.ext[ext_index].param_decls if (bock_item_index + 1 <= len(ast_tree.ext[ext_index].body.block_items)): if (mode == "insert_after"): block_items_before = ast_tree.ext[ ext_index].body.block_items[:bock_item_index + 1] if (mode == "insert_before"): block_items_before = ast_tree.ext[ ext_index].body.block_items[:bock_item_index] if (len(ast_tree.ext[ext_index].body.block_items) > 1): if (mode == "insert_after"): block_items_after = ast_tree.ext[ext_index].body.block_items[ bock_item_index + 1:] if (mode == "insert_before"): block_items_after = ast_tree.ext[ext_index].body.block_items[ bock_item_index:] block_items_before.append(new_node) changed_body = c_ast.Compound(block_items_before + block_items_after) changed_ext = c_ast.FuncDef(func_def_decl, para_decl, changed_body) ext_before.append(changed_ext) ast_tree = c_ast.FileAST(ext_before + ext_after) return ast_tree
def check_value(ast_tree, ext_index, bock_item_index, var_name, func_name): Cast = c_ast.Cast( c_ast.Typename( None, [], c_ast.PtrDecl([], c_ast.TypeDecl(None, [], c_ast.IdentifierType(['void'])))), c_ast.ID(var_name)) func_call = c_ast.FuncCall( c_ast.ID('check_value'), c_ast.ExprList([ c_ast.UnaryOp('&', c_ast.ID('global_log')), Cast, c_ast.Constant('string', '"' + var_name + '"'), c_ast.Constant('string', '"' + func_name + '"'), c_ast.Constant('int', str(len(var_name))), c_ast.Constant('int', str(len(func_name))) ])) new_node = c_ast.If( c_ast.BinaryOp('==', func_call, c_ast.Constant('int', '0')), c_ast.Compound([ c_ast.FuncCall( c_ast.ID('printf'), c_ast.ExprList([ c_ast.Constant('string', '"%s\\n"'), c_ast.Constant('string', '"Attack Detected"') ])), c_ast.FuncCall(c_ast.ID('exit'), c_ast.ExprList([c_ast.Constant('int', '1')])) ]), None) return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, "insert_before")
def visit_Switch(self, node): if type(node.stmt) is c_ast.Compound: declarations = [] new_block_items = [] for item in node.stmt.block_items: if type(item) is c_ast.Decl: declarations.append(item) else: new_block_items.append(item) if len(self.parents) > 0 and len(declarations) > 0: node.stmt.block_items = new_block_items new_switch_block = c_ast.Compound(declarations + [node]) if hasattr(self.parents[-1], "block_items"): index = self.parents[-1].block_items.index(node) self.parents[-1].block_items.remove(node) self.parents[-1].block_items.insert( index, new_switch_block) elif hasattr(self.parents[-1], "iftrue") and self.parents[-1].iftrue == node: self.parents[-1].iftrue = new_switch_block elif hasattr(self.parents[-1], "iffalse") and self.parents[-1].iffalse == node: self.parents[-1].iffalse = new_switch_block else: # TODO: The three cases above most likely don't cover all possible contexts in which a switch can # occur. This works on both case studies, so sufficient as of now. But for future use, one might # want to evaluate from the C standard which contexts are generaly possible! sys.stderr.write( "Can not identify the context of a switch statement that is contained in " + str(type(self.parents[-1])))
def define_sizeof_modifier_type(t): # setup the toplevel call if t.get_typename(): argument_ast = t.get_reference()("storage") else: argument_ast = t.define("storage") prefix = "fffc_get_sizeof_" desired_name = CGenerator().visit(argument_ast) suffix = encode_hash(desired_name) function_name = prefix + suffix # build the underlying function call underlying_call = get_sizeof_pointer_to_type(t.underlying_type, c_ast.ID("storage")) # build this just as above, except with the call in place of the sizeof storage_tdecl = c_ast.Decl("storage", [], [], [], c_ast.PtrDecl([], argument_ast), None, None) func_tdecl = c_ast.TypeDecl( function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"])) funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl) funcdef = c_ast.FuncDef( c_ast.Decl(function_name, [], [], [], funcdecl, None, None), None, c_ast.Compound([c_ast.Return(underlying_call)]), ) comment = "/* " + desired_name + "*/\n" kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl) return comment, kr_funcdecl, funcdef
def compile_node(lookup, decl_code, node): code = [] stack = {} inargs = [] pre = node.type + '_pre' post = node.type + '_post' compile_ast(lookup, stack, inargs, decl_code, code, pre) for word in node.quotation: compile_ast(lookup, stack, inargs, decl_code, code, word) compile_ast(lookup, stack, inargs, decl_code, code, node.type) call = code[-1] end_stack = deepcopy(stack) end_inargs = deepcopy(inargs) end_code = [] compile_ast(lookup, end_stack, end_inargs, decl_code, end_code, post) outargs = [a for args in end_stack.values() for a in args] assign_results(outargs, end_code) end_code.append(c_ast.Return(None)) end = c_ast.Compound(end_code) condition = c_ast.If(call, end, None) code[-1] = condition compile_ast(lookup, stack, inargs, decl_code, code, post) outargs = [a for args in stack.values() for a in args] name = gensym(node.type) fn = fndecl(name, inargs, outargs, code) decl_code.append(fn) lookup[name] = (inargs, outargs) return name
def __for_loop(self, depth: int) -> c_ast.For: """ A helper function to construct a for loop corresponding to allocating one dimension of an array. Recursively calls itself to generate next levels or generates an initialisation line if it is the last level. Example: for(i_2 = 0; i_2 < N; i_2++) { ... } :param depth: :return: C-ast.For """ i = self.counter_prefix + str(depth) init = c_ast.DeclList([ c_ast.Decl(c_ast.ID(i), [], [], [], c_ast.TypeDecl(i, [], c_ast.IdentifierType(['int'])), c_ast.Constant('int', '0'), '') ]) cond = c_ast.BinaryOp('<', c_ast.ID(i), self.sizes[depth]) nxt = c_ast.Assignment('++', c_ast.ID(i), None) stmt = c_ast.Compound([]) if depth < len(self.sizes) - 1: stmt.block_items = [ self.__malloc_assign(depth + 1), self.__for_loop(depth + 1) ] else: stmt.block_items = [self.initialiser(depth + 1)] return c_ast.For(init, cond, nxt, stmt)
def createMain(self): #Main Function #Declaration z1 = c_ast.TypeDecl('args',[],c_ast.IdentifierType(['int'])) args = c_ast.Decl('args',[],[],[],z1,None,None) z2= c_ast.PtrDecl([],c_ast.TypeDecl('argv',[],c_ast.IdentifierType(['char']))) z3=c_ast.ArrayDecl(z2,None,[]) argv = c_ast.Decl('argv',[],[],[],z3,None,None) params=c_ast.ParamList([args,argv]) mainDec=c_ast.FuncDecl(params,c_ast.TypeDecl('main',[],c_ast.IdentifierType(['int']))) # insertTest(functionName,varVals,varTypes) #Body ##Signal sigalrm=c_ast.ID(name="14") funcCast=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['void'])) paramCast=c_ast.ParamList([c_ast.Typename(name=None,quals=[],type=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['int'])))]) typeFunc=c_ast.PtrDecl(type=c_ast.FuncDecl(paramCast,funcCast),quals=[]) kchild=c_ast.Cast(to_type=c_ast.Typename(name=None, quals=[],type=typeFunc),expr=c_ast.ID(name="kill_child")) expressList = [sigalrm,kchild] signalStmt=c_ast.FuncCall(c_ast.ID(name="signal"),c_ast.ExprList(expressList)) ##Return returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([signalStmt,returnStmt]) return c_ast.FuncDef(mainDec,None,comp)
def perm_refer_to_var(fn: ca.FuncDef, ast: ca.FileAST, indices: Indices, region: Region, random: Random) -> bool: """Add `if (variable) {}` or `if (struct.member) {}` in a random place. This will get optimized away but may affect regalloc.""" # Find expression to insert, searching within the randomization region. cands: List[Expression] = [ expr for expr in get_block_expressions(fn.body, region) if isinstance(expr, (ca.StructRef, ca.ID)) ] if not cands: return False expr = random.choice(cands) if ast_util.is_effectful(expr): return False type: SimpleType = decayed_expr_type(expr, build_typemap(ast)) if isinstance(type, ca.TypeDecl) and isinstance(type.type, (ca.Struct, ca.Union)): expr = ca.UnaryOp("&", expr) if random.choice([True, False]): expr = ca.UnaryOp("!", expr) # Insert it wherever -- possibly outside the randomization region, since regalloc # can act at a distance. (Except before a declaration.) ins_cands = get_insertion_points(fn, Region.unbounded()) ins_cands = [c for c in ins_cands if not isinstance(c[2], ca.Decl)] if not ins_cands: return False cond = copy.deepcopy(expr) stmt = ca.If(cond=cond, iftrue=ca.Compound(block_items=[]), iffalse=None) tob, toi, _ = random.choice(ins_cands) ast_util.insert_statement(tob, toi, stmt) return True
def _DoPrintfSplitter(call: c_ast.FuncCall, parent, use_specialized_printf): args: List = call.args.exprs fmt_pieces = TokenizeFormatString(args[0].value[1:-1]) assert len(fmt_pieces) >= 1 if use_specialized_printf and len(fmt_pieces) == 1: s = fmt_pieces[0] if len(s) <= 1 or s[0] != "%": call.name.name = "write_s" args.insert(0, CONST_STDOUT) return else: call.name.name = GetSingleArgPrintForFormat(s) args[0] = CONST_STDOUT return stmts = common.GetStatementList(parent) if not stmts: stmts = [call] common.ReplaceNode(parent, call, c_ast.Compound(stmts)) calls = [] args = args[1:] # skip the format string # note this has a small bug: we should evaluate all the # args and then print them instead of interleaaving # computation and printing. for f in fmt_pieces: arg = None if f[0] == '%' and len(f) > 1: arg = args.pop(0) c = MakePrintfCall(f, arg, use_specialized_printf) calls.append(c) pos = stmts.index(call) stmts[pos:pos + 1] = calls
def _build_handle_function(functions): """ Wraps the switch statement in a function definition """ case_statement = _build_case(functions) available_check = c_ast.If( c_ast.BinaryOp( '<', c_ast.FuncCall( c_ast.ID('mailbox_available'), c_ast.ExprList([c_ast.Constant('int', '2')]) ), c_ast.Constant('int', '4') ), c_ast.Return(None), None ) handle_decl = c_ast.FuncDecl( None, c_ast.TypeDecl('_handle_events', [], c_ast.IdentifierType(['void'])), ) command_decl = c_ast.Decl('command', [], [], [], c_ast.TypeDecl('command', [], c_ast.IdentifierType(['int'])), [], []) command_read = _generate_read('command') body = c_ast.Compound([available_check, command_decl, command_read, case_statement]) return c_ast.FuncDef(handle_decl, [], body)
def nested_for_loop(node, inner_loop_body, loop_iterator_base, rename_index=0): """ Recursively create nested for loops for copying a multi-dimensional array. """ if isinstance(node.type.type, c_ast.ArrayDecl): # Multi-dimensional array, recurse to generate inner loop for_loop_body = nested_for_loop(node.type, inner_loop_body, loop_iterator_base, rename_index + 1) else: # Single or last dimension of array for_loop_body = [inner_loop_body] # Declare iterator loop_iterator = c_ast.ID("%s_i%d" % (loop_iterator_base, rename_index)) loop_iterator_decl = c_ast.Decl( loop_iterator.name, [], [], [], c_ast.TypeDecl(loop_iterator.name, [], c_ast.IdentifierType(["int"])), None, None) # For loop array_size = node.type.dim for_loop = c_ast.For( c_ast.Assignment('=', loop_iterator, c_ast.Constant("int", "0")), c_ast.BinaryOp('<', loop_iterator, array_size), c_ast.UnaryOp('p++', loop_iterator), c_ast.Compound(for_loop_body)) return [loop_iterator_decl, for_loop]
def add_jump_guard(ast_to_guard, phase_var, round_var, label): guarded_ast = c_ast.If( c_ast.BinaryOp( '&&', c_ast.BinaryOp('==', c_ast.ID(phase_var), c_ast.ID('PHASE')), c_ast.BinaryOp('==', c_ast.ID(round_var), c_ast.ID(label))), ast_to_guard, None) return c_ast.Compound([guarded_ast])
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)
def test_nested_else_if_line_breaks(self): generator = c_generator.CGenerator() test_ast1 = c_ast.If(None, None, None) test_ast2 = c_ast.If(None, None, c_ast.If(None, None, None)) test_ast3 = c_ast.If(None, None, c_ast.If(None, None, c_ast.If(None, None, None))) test_ast4 = c_ast.If( None, c_ast.Compound([]), c_ast.If(None, c_ast.Compound([]), c_ast.If(None, c_ast.Compound([]), None))) self.assertEqual(generator.visit(test_ast1), 'if ()\n \n') self.assertEqual(generator.visit(test_ast2), 'if ()\n \nelse\n if ()\n \n') self.assertEqual(generator.visit(test_ast3), 'if ()\n \nelse\n if ()\n \nelse\n if ()\n \n') self.assertEqual( generator.visit(test_ast4), 'if ()\n{\n}\nelse\n if ()\n{\n}\nelse\n if ()\n{\n}\n')
def createOutputIf(self, expr): expressList = [c_ast.Constant(type='int', value='0')] funcCall = c_ast.FuncCall(c_ast.ID(name="assert"), c_ast.ExprList(expressList)) if_all = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='__out_var'), op='==', right=expr), c_ast.Compound([funcCall]), iffalse=None) return (if_all)
def addTestFunction(ast, expectedOutput, testFxn, initVars, initList): varList = [] exprList = [] fxnName = '' inFxn = False listi = 0 for i in range(len(initVars)): v = initVars[i] if inFxn: exprList.append(c_ast.Constant('int', initList[listi])) listi += 1 if (')' in v): inFxn = False newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList(exprList)) varList.append(newVar) exprList = [] else: if ('(' in v): fxnName = v[:v.index('(')] if (v[v.index('(')+1] != ')'): inFxn = True exprList.append(c_ast.Constant('int', initList[listi])) listi += 1 else: newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList([])) varList.append(newVar) else: newVar = c_ast.Assignment('=', c_ast.ID(v), c_ast.Constant('int', initList[listi])) listi += 1 varList.append(newVar) fxnDecl = c_ast.FuncDecl(None, c_ast.TypeDecl('klee_test_entry', [], c_ast.IdentifierType(['void']))) fxnCall = c_ast.FuncCall(c_ast.ID(testFxn), c_ast.ExprList([])) binaryOp = c_ast.BinaryOp('==', fxnCall, c_ast.Constant('int', expectedOutput)) ifFalse = c_ast.Compound([c_ast.FuncCall(c_ast.ID('klee_silent_exit'), c_ast.ExprList([c_ast.Constant('int', '0')]))]) ifTrue = c_ast.Compound([]) blockItems = [] for v in varList: blockItems.append(v) blockItems.append(c_ast.If(binaryOp, ifTrue, ifFalse)) fxnBody = c_ast.Compound(blockItems) fxnNode = c_ast.FuncDef(fxnDecl, None, fxnBody) ast.ext.append(fxnNode)
def __init__(self, decl, typedefs): self.return_interface = _type_to_interface(decl.type, typedefs) self.name = decl.type.declname self.docstring = _get_docstring(decl.coord) self.arg_interfaces = [] self.args = [] self.blocks = False self.coord = decl.coord block_contents = [] post_block_contents = [] func_args = [] if decl.args: for i, arg in enumerate(decl.args.params): if type(arg) is c_ast.EllipsisParam: raise RuntimeError("vararg functions not supported") interface = _type_to_interface(arg.type, typedefs) if type(interface) is VoidWrapper: continue block_contents.extend(interface.pre_argument('arg' + str(i))) post_block_contents.extend( interface.post_argument('arg' + str(i))) func_args.append(c_ast.ID('arg' + str(i))) self.arg_interfaces.append(interface) self.blocks = self.blocks | interface.blocks if arg.name: self.args.append(arg.name) else: self.args.append(f'arg{len(self.args)}') function_call = c_ast.FuncCall(c_ast.ID(self.name), c_ast.ExprList(func_args)) self.returns = type(self.return_interface) is not VoidWrapper if self.returns: ret_assign = c_ast.Decl('ret', [], [], [], c_ast.TypeDecl('ret', [], decl.type.type), function_call, []) block_contents.append(ret_assign) block_contents.append(_generate_write('return_command')) block_contents.extend(post_block_contents) block_contents.append(_generate_write('ret')) self.blocks = True else: block_contents.append(function_call) if self.blocks: block_contents.append(_generate_write('return_command')) else: block_contents.append(_generate_write('void_command')) block_contents.extend(post_block_contents) self.call_ast = c_ast.Compound(block_contents) self.filename = decl.coord.file
def work(self, new_stuffs): for parent, child in self.target_location: if isinstance(child, c_ast.Return): new_stuffs_copy = new_stuffs[:-1] + [ c_ast.FuncCall( name=c_ast.ID(name="_RETTYPE"), args=c_ast.ExprList(exprs=[ child.expr, c_ast.Constant(type='int', value=str(len(new_stuffs) - 1)) ])) ] + new_stuffs[-1:] else: new_stuffs_copy = new_stuffs if isinstance(parent, c_ast.Compound): child_loc = parent.block_items.index(child) parent.block_items = parent.block_items[: child_loc] + new_stuffs_copy + parent.block_items[ child_loc + 1:] elif isinstance(parent, c_ast.If): if parent.iftrue == child: parent.iftrue = c_ast.Compound(block_items=new_stuffs_copy) elif parent.iffalse == child: parent.iffalse = c_ast.Compound( block_items=new_stuffs_copy) elif isinstance(parent, c_ast.While): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.For): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.DoWhile): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.Label): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy)
def insert_in_If(self, node, stmt): # Insert at start of compound block if isinstance(node.iftrue, c_ast.Compound): if node.iftrue.block_items: node.iftrue.block_items.insert(0, stmt) else: node.iftrue.block_items = [stmt] # Replace empty statement elif isinstance(node.iftrue, c_ast.EmptyStatement): node.iftrue = stmt else: compound = c_ast.Compound([stmt, node.iftrue]) node.iftrue = compound