예제 #1
0
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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
 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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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)