Exemple #1
0
def element_selection(expr, symbol_table):
    instrs = symbol_table['__ expression __'](left_exp(expr), symbol_table)
    # if we are loading the structure then just remove the Load instr, calculate the elements offset and Load that elem
    if is_load(instrs):
        return element_instrs(
            c_type(left_exp(expr)), right_exp(expr), loc(expr), load_instrs=all_but_last(instrs, Loads, loc(expr))
        )

    struct_size, member_size = size(c_type(left_exp(expr))), size_arrays_as_pointers(c_type(expr))
    addr_instrs = add(  # calculate the loaded structured members address
        load_stack_pointer(loc(expr)),
        push(struct_member_offset(c_type(left_exp(expr)), right_exp(expr)), loc(expr)),
        loc(expr)
    )
    return chain(  # copy the element then move it to the base of the structure and deallocate everything else
        set_instr(
            chain(  # load the value in question if its not an array (which is just an address ...)
                (addr_instrs if isinstance(c_type(expr), ArrayType) else load(addr_instrs, member_size, loc(expr))),
                add(load_stack_pointer(loc(expr)), push((struct_size + member_size), loc(expr)), loc(expr)),
            ),
            member_size,
            loc(expr)
        ),
        allocate(-(struct_size - member_size), loc(expr))  # deallocate structure and copied member (set leaves value)
    )
Exemple #2
0
def element_selection(expr, symbol_table):
    instrs = symbol_table['__ expression __'](left_exp(expr), symbol_table)
    # if we are loading the structure then just remove the Load instr, calculate the elements offset and Load that elem
    if is_load(instrs):
        return element_instrs(c_type(left_exp(expr)),
                              right_exp(expr),
                              loc(expr),
                              load_instrs=all_but_last(instrs, Loads,
                                                       loc(expr)))

    struct_size, member_size = size(c_type(
        left_exp(expr))), size_arrays_as_pointers(c_type(expr))
    addr_instrs = add(  # calculate the loaded structured members address
        load_stack_pointer(loc(expr)),
        push(struct_member_offset(c_type(left_exp(expr)), right_exp(expr)),
             loc(expr)), loc(expr))
    return chain(  # copy the element then move it to the base of the structure and deallocate everything else
        set_instr(
            chain(  # load the value in question if its not an array (which is just an address ...)
                (addr_instrs if isinstance(c_type(expr), ArrayType) else load(
                    addr_instrs, member_size, loc(expr))),
                add(load_stack_pointer(loc(expr)),
                    push((struct_size + member_size), loc(expr)), loc(expr)),
            ),
            member_size,
            loc(expr)),
        allocate(-(struct_size - member_size), loc(
            expr))  # deallocate structure and copied member (set leaves value)
    )
Exemple #3
0
def compound_statement(stmnt, symbol_table):
    stack, statement = utils.symbol_table.get_symbols(symbol_table, '__ stack __', '__ statement __')
    stack_pointer, symbol_table = stack.stack_pointer, utils.symbol_table.push(symbol_table)
    for instr in chain.from_iterable(imap(statement, chain.from_iterable(stmnt), repeat(symbol_table))):
        yield instr
    for instr in allocate(stack.stack_pointer - stack_pointer, loc(stmnt)):  # deallocate any definitions that may occur
        yield instr
    stack.stack_pointer = (utils.symbol_table.pop(symbol_table) or True) and stack_pointer  # reset stack pointer ...
Exemple #4
0
def statement(stmnt, symbol_table):
    is_expression = isinstance(stmnt, expressions.Expression)

    # Set entry point to False if its an expression or use statement function if present otherwise None.
    instrs = rules(statement)[type(stmnt)](stmnt, symbol_table)
    # Almost all Expression statements leave a value on the stack, so we must remove it.
    if stmnt and is_expression:
        instrs = chain(instrs, allocate(-size(c_type(stmnt), overrides={VoidType: 0}), loc(stmnt)))
    return instrs
Exemple #5
0
def comma_expression(expr, symbol_table):
    expression = symbol_table['__ expression __']
    return chain(
        chain.from_iterable(
            chain(
                expression(e, symbol_table),
                allocate(
                    -size_arrays_as_pointers(c_type(e),
                                             overrides={VoidType: 0}), loc(e)))
            for e in exp(expr)[:-1]), expression(exp(expr)[-1], symbol_table))
Exemple #6
0
def comma_expression(expr, symbol_table):
    expression = symbol_table['__ expression __']
    return chain(
        chain.from_iterable(
            chain(
                expression(e, symbol_table),
                allocate(-size_arrays_as_pointers(c_type(e), overrides={VoidType: 0}), loc(e))
            ) for e in exp(expr)[:-1]
        ),
        expression(exp(expr)[-1], symbol_table)
    )
Exemple #7
0
def function_call(expr, symbol_table):
    assert not isinstance(c_type(expr), ArrayType)
    l, return_instr = loc(expr), Pass(loc(expr))
    total_size_of_arguments = sum(imap(size_arrays_as_pointers, imap(c_type, right_exp(expr))))
    return_size = size(c_type(expr), overrides={VoidType: 0})
    omit_pointer_for_return_value = not return_size

    # if omit_pointer_for_return_value:
    #     # if the function call is a statement or its return type has zero size.
    #     # lets do some minor optimizations, since function calls already quite expensive as it is.
    #     expr.c_type = VoidType(loc(l))  # change the return type of the expression to void.
    #     # since we are omitting the return pointer, we have to update the parameter offsets, since they are calculated
    #     # assuming that a return pointer is added ...
    #     # all sets should be decrease by size(void_pointer) for this expression but this may not be true for other
    #     # function call expressions that may actually use the return value of this as such ... :(
    # we would need to check if the functions return value is ALWAYS ignored if and only if then can we omit
    # the return pointer for know its only applicable for for functions whose return size is zero ...
    # TODO: post-compilation optimization that optimizes functions whose returned values is ALWAYS ignored.
    expression = symbol_table['__ expression __']
    return chain(
        # Allocate space for return value, save frame.
        allocate(return_size, l),
        push_frame(
            # Push arguments in reverse order (right to left) ...
            chain.from_iterable(imap(expression, reverse(right_exp(expr)), repeat(symbol_table))),
            location=l,
            total_size_of_arguments=total_size_of_arguments,
            omit_pointer_for_return_value=omit_pointer_for_return_value
        ),
        push(Address(return_instr, l), l),  # make callee aware of were to return to.
        call_function(expr, symbol_table),
        (return_instr,),
        # Pop Frame, first stack pointer then base stack pointer
        pop_frame(
            location=l,
            total_size_of_arguments=total_size_of_arguments,
            omit_pointer_for_return_value=omit_pointer_for_return_value
        )
    )
Exemple #8
0
def function_call(expr, symbol_table):
    assert not isinstance(c_type(expr), ArrayType)
    l, return_instr = loc(expr), Pass(loc(expr))
    total_size_of_arguments = sum(
        imap(size_arrays_as_pointers, imap(c_type, right_exp(expr))))
    return_size = size(c_type(expr), overrides={VoidType: 0})
    omit_pointer_for_return_value = not return_size

    # if omit_pointer_for_return_value:
    #     # if the function call is a statement or its return type has zero size.
    #     # lets do some minor optimizations, since function calls already quite expensive as it is.
    #     expr.c_type = VoidType(loc(l))  # change the return type of the expression to void.
    #     # since we are omitting the return pointer, we have to update the parameter offsets, since they are calculated
    #     # assuming that a return pointer is added ...
    #     # all sets should be decrease by size(void_pointer) for this expression but this may not be true for other
    #     # function call expressions that may actually use the return value of this as such ... :(
    # we would need to check if the functions return value is ALWAYS ignored if and only if then can we omit
    # the return pointer for know its only applicable for for functions whose return size is zero ...
    # TODO: post-compilation optimization that optimizes functions whose returned values is ALWAYS ignored.
    expression = symbol_table['__ expression __']
    return chain(
        # Allocate space for return value, save frame.
        allocate(return_size, l),
        push_frame(
            # Push arguments in reverse order (right to left) ...
            chain.from_iterable(
                imap(expression, reverse(right_exp(expr)),
                     repeat(symbol_table))),
            location=l,
            total_size_of_arguments=total_size_of_arguments,
            omit_pointer_for_return_value=omit_pointer_for_return_value),
        push(Address(return_instr, l),
             l),  # make callee aware of were to return to.
        call_function(expr, symbol_table),
        (return_instr, ),
        # Pop Frame, first stack pointer then base stack pointer
        pop_frame(location=l,
                  total_size_of_arguments=total_size_of_arguments,
                  omit_pointer_for_return_value=omit_pointer_for_return_value))
Exemple #9
0
def union_initializer(expr, symbol_table):
    return chain(
        allocate(size(c_type(expr)) - size(c_type(expr[0])), loc(expr)), numeric_initializer(expr, symbol_table)
    )
Exemple #10
0
            chain(
                expression(e, symbol_table),
                allocate(
                    -size_arrays_as_pointers(c_type(e),
                                             overrides={VoidType: 0}), loc(e)))
            for e in exp(expr)[:-1]), expression(exp(expr)[-1], symbol_table))


# Entry point to all expression or expression statements
def expression(expr, symbol_table):
    return rules(expression)[type(expr)](expr, symbol_table)


expression_funcs = unary_expression, postfix_expression, ternary_expression, initializer_expression
set_rules(
    expression,
    chain((
        (EmptyExpression, lambda expr, *_: allocate(
            size(c_type(expr), overrides={VoidType: 0}), loc(expr))),
        (ConstantExpression, constant_expression),
        (CastExpression, cast_expression),
        (IdentifierExpression, identifier_expression),
        (CommaExpression, comma_expression),
        (BinaryExpression, binary_expression),
        (AssignmentExpression, binary_expression),
        (CompoundAssignmentExpression, binary_expression),
    ),
          chain.from_iterable(
              imap(izip, imap(rules, expression_funcs),
                   imap(repeat, expression_funcs)))))
Exemple #11
0
            chain(
                expression(e, symbol_table),
                allocate(-size_arrays_as_pointers(c_type(e), overrides={VoidType: 0}), loc(e))
            ) for e in exp(expr)[:-1]
        ),
        expression(exp(expr)[-1], symbol_table)
    )


# Entry point to all expression or expression statements
def expression(expr, symbol_table):
    return rules(expression)[type(expr)](expr, symbol_table)
expression_funcs = unary_expression, postfix_expression, ternary_expression, initializer_expression
set_rules(
    expression,
    chain(
        (
            (EmptyExpression, lambda expr, *_: allocate(size(c_type(expr), overrides={VoidType: 0}), loc(expr))),
            (ConstantExpression, constant_expression),
            (CastExpression, cast_expression),
            (IdentifierExpression, identifier_expression),
            (CommaExpression, comma_expression),

            (BinaryExpression, binary_expression),
            (AssignmentExpression, binary_expression),
            (CompoundAssignmentExpression, binary_expression),
        ),
        chain.from_iterable(imap(izip, imap(rules, expression_funcs), imap(repeat, expression_funcs)))
    )
)
Exemple #12
0
def const_union_expr(expr):
    assert len(exp(expr)) <= 1
    return chain(  # allocate rest ...
        allocate(
            size(c_type(expr)) - sum(imap(size, imap(c_type, exp(expr)))),
            loc(expr)), const_struct_expr(exp(expr)))
Exemple #13
0
def const_union_expr(expr):
    assert len(exp(expr)) <= 1
    return chain(                   # allocate rest ...
        allocate(size(c_type(expr)) - sum(imap(size, imap(c_type, exp(expr)))), loc(expr)),
        const_struct_expr(exp(expr))
    )
Exemple #14
0
def update_stack(source_stack_pointer, target_stack_pointer, location):
    return allocate(source_stack_pointer - target_stack_pointer, location)