def _(function: ast.Function) -> None: # Rename procedures if function.return_type == core.ast.Void(): print_if_verbose("Replacing func with proc: " + function.name) function.name = function.name.replace("func", "proc") for stmt in function.stmts: visit(stmt)
def _instrument_statements(statements: List[ast.ASTNode]) -> List[ast.ASTNode]: """Includes a label before the return statements""" instrumented_stmts = [] for stmt in statements: if isinstance(stmt, ast.Return): print_if_verbose(f"Return stmt: {stmt.to_str()}") label_ast = ast.Label(generate_label()) instrumented_stmts.append(label_ast) visit(stmt) instrumented_stmts.append(stmt) return instrumented_stmts
def _(program: ast.Program) -> None: print_if_verbose("") print_if_verbose("*" * 80) print_if_verbose("* FUNC TO PROC INSTRUMENTATION") print_if_verbose("*" * 80) for function in program.functions: visit(function) visit(program.main)
def _(program: ast.Program): print_if_verbose("") print_if_verbose("*" * 80) print_if_verbose("* RETURN INSTRUMENTATION") print_if_verbose("*" * 80) for function in program.functions: visit(function) visit(program.main)
def count_functions_generated_by_group() -> Dict[str, int]: """Returns a dictionary with the number of functions created by each function group (in the distribution)""" messages = ["Functions yet to generate: "] func_generated_per_group = dict() for func_group_name, func_dict in distribution.items(): number_func_generated = sum(1 for function in program.functions if func_dict["condition"](function)) func_generated_per_group[func_group_name] = number_func_generated messages.extend([ func_group_name, ": ", str(func_dict["total"] - number_func_generated), "; " ]) messages.append("Total functions generated = {}.".format( len(program.functions))) print_if_verbose("".join(messages)) return func_generated_per_group
def _(program: ast.Program, **kwargs) -> ast.Program: print_if_verbose() print_if_verbose("*" * 80) print_if_verbose("* FIX PTR LITERALS") print_if_verbose("*" * 80) for function in program.functions: visit(function, program, **kwargs) visit(program.main, program, **kwargs) return program
def generate_program_with_function_distribution(distribution, args, remove_unwanted_functions=True ): removed = [] def remove_func(f): removed.append(f.name) program.functions.remove(f) def remove_last(cmp): for f in reversed(program.functions[:]): if cmp(f): remove_func(f) return def count_functions_generated_by_group() -> Dict[str, int]: """Returns a dictionary with the number of functions created by each function group (in the distribution)""" messages = ["Functions yet to generate: "] func_generated_per_group = dict() for func_group_name, func_dict in distribution.items(): number_func_generated = sum(1 for function in program.functions if func_dict["condition"](function)) func_generated_per_group[func_group_name] = number_func_generated messages.extend([ func_group_name, ": ", str(func_dict["total"] - number_func_generated), "; " ]) messages.append("Total functions generated = {}.".format( len(program.functions))) print_if_verbose("".join(messages)) return func_generated_per_group # Generate a program with its main function program = ast.Program() program.main = main_function = ast.Function("main", ast.SignedInt(), []) while True: # Create stmts in the main body main_function.stmts.append(generate_stmt_func(program, main_function)) func_number_by_group = count_functions_generated_by_group() # Until all the wanted functions are generated if all(func_number_by_group[func_group_name] >= func_dict["total"] for func_group_name, func_dict in distribution.items()): break # All the wanted functions were created # Remove the generated functions not included in any group in the distribution if remove_unwanted_functions: for func in program.functions[:]: if not any(func_dict["condition"](func) for func_dict in distribution.values()): remove_func(func) # Adjust the amount of functions in each group for func_group_name, func_dict in distribution.items(): delta = func_number_by_group[func_group_name] - func_dict["total"] print_if_verbose("Removing {} {}".format(delta, func_group_name)) for _ in range(delta): remove_last(func_dict["condition"]) count_functions_generated_by_group() before = program.functions[:] # Substitute calls to removed functions print_if_verbose("") print_if_verbose("*" * 80) print_if_verbose("* SUBSTITUTIONS") print_if_verbose("*" * 80) function_subs.visit(program, removed) total_number_of_funcs_to_generate = sum( dictionary["total"] for (key, dictionary) in distribution.items()) after = program.functions[:] if len(after) != total_number_of_funcs_to_generate and args.verbose: print_if_verbose("") print_if_verbose("*" * 80) print_if_verbose("* WARNING: NEW FUNCTIONS") print_if_verbose("*" * 80) for func in after: if func not in before: print_if_verbose(func) ### # Generate statement invocations to reach a ratio expr_invocation/stmt_invocation = 2 ### # Disable invocations in the generations of parameter expressions new_probs = {False: 1, True: 0} old_probs = dict(probs.call_prob) probs.call_prob = new_probs # Generate statement invocations print_if_verbose("") print_if_verbose("*" * 80) print_if_verbose("* GENERATING INVOCATIONS") print_if_verbose("*" * 80) for func in program.functions: amount = 2 * program.invocation_as_expr[ func.name] - program.invocation_as_stmt[func.name] print_if_verbose( "{} needs '2 * {} - {} = {}' statement invocations.".format( func.name, program.invocation_as_expr[func.name], program.invocation_as_stmt[func.name], amount)) if amount <= 0: continue for _ in range(amount): invoc = generate_stmt_invocation(program, program.main, invoked_func=func) main_function.stmts.append(invoc) # Restore probability probs.call_prob = dict(old_probs) ### # Add return statement ### main_function.stmts.append( generate_stmt_return(program, main_function, exp=None)) return program
def _(literal: ast.Literal, program: ast.Program, function: ast.Function, **kwargs) -> ast.ASTNode: if isinstance(literal.type, ast.Pointer): print_if_verbose("*" * 80) print_if_verbose(function.name) print_if_verbose(repr(literal.type)) try: global_var = program.global_vars[literal.type.type] except KeyError: print_if_verbose("NEW") global_var = generators.generate_global_var( program, function, literal.type.type) new_literal = ast.UnaryExpression("/* PTR LITERAL */ & ", global_var, literal.type.type, post_op=False) print_if_verbose(new_literal) print_if_verbose("*" * 80) return new_literal return literal
def _(invocation: ast.Invocation) -> None: # Rename procedures if invocation.return_type == core.ast.Void(): invocation.func_name = invocation.func_name.replace("func", "proc") print_if_verbose("Replacing: " + invocation.func_name)