Example #1
0
def compound_assignment(expr, symbol_table):
    assert all(imap(isinstance, imap(c_type, (left_exp(expr), right_exp(expr))), repeat(NumericType)))
    assert not isinstance(c_type(left_exp(expr)), ArrayType)

    if isinstance(left_exp(expr), IdentifierExpression) and \
       base_c_type(c_type(left_exp(expr))) == base_c_type(c_type(right_exp(expr))) and \
       size(c_type(left_exp(expr))) == size(c_type(right_exp(expr))):
        # check that both operands are of the same kind (integral vs numeric) and have the same size ...
        return simple_numeric_assignment_no_casting(expr, symbol_table, rules(compound_assignment)[oper(expr)])

    max_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))  # cast to largest type.
    expression = symbol_table['__ expression __']
    left_instrs = cast(  # cast to max_type
        patch_comp_left_instrs(expression(left_exp(expr), symbol_table),  loc(expr), size(c_type(left_exp(expr)))),
        c_type(left_exp(expr)),
        max_type,
        loc(expr),
    )
    right_instrs = cast(expression(right_exp(expr), symbol_table), c_type(right_exp(expr)), max_type, loc(expr))
    return patch_comp_assignment(
        cast(  # Cast the result back, swap the value and the destination address call set to save.
            rules(compound_assignment)[oper(expr)](
                left_instrs,
                right_instrs,
                loc(expr),
                (max_type, c_type(left_exp(expr)), c_type(right_exp(expr)))
            ),
            max_type,
            c_type(expr),
            loc(expr)
        ),
        c_type(expr),
        loc(expr),
    )
Example #2
0
def patch_comp_assignment(instrs, expr_type, location):
    # At this point the stack contains the Address followed by the calculated value ...
    # we need to swap them and call set, but we mut be careful that both have the same size before calling swap
    # or we could corrupt the value ...
    if size(expr_type) == size(void_pointer_type):  # result type and pointer type (address) equal no alignment required
        return chain(instrs, set_instr(swap(size(void_pointer_type), location), size(void_pointer_type), location))

    if size(expr_type) < size(void_pointer_type):  # size of result type is less than address we need to align
        if isinstance(expr_type, DoubleType):  # since we are using cast to the alignment we need too interpret
            assert size(double_type) == size(long_type)   # result type as integral type for casting may change value
            expr_type = LongType(location, unsigned=True)
        elif isinstance(expr_type, FloatType):
            assert size(float_type) == size(integer_type)
            expr_type = IntegerType(location, unsigned=True)

        return cast(  # convert the value back to its original size removing any alignment added bytes after set ...
            set_instr(  # set values assuming little endian architecture  TODO: check on that assertion!
                chain(cast(instrs, expr_type, void_pointer_type, location), swap(size(void_pointer_type), location)),
                size(expr_type),  # if sizes differ, cast value to pointer type extending bytes, and swap
                location
            ),
            void_pointer_type,
            expr_type,
            location
        )
    else:
        raise ValueError('{l} unable to patch compound assignment value size {s} exceeds address size {a}'.format(
            l=location, s=size(expr_type), a=size(void_pointer_type)
        ))
Example #3
0
def relational_operators(expr, symbol_table):
    max_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))
    expression = symbol_table['__ expression __']
    if isinstance(max_type, ArrayType):
        max_type = PointerType(c_type(max_type), loc(max_type))
    left_instrs = expression(left_exp(expr), symbol_table)
    right_instrs = expression(right_exp(expr), symbol_table)

    return rules(relational_operators)[oper(expr)](
        cast(left_instrs, c_type(left_exp(expr)), max_type, loc(expr)),
        cast(right_instrs, c_type(right_exp(expr)), max_type, loc(expr)),
        loc(expr),
        (c_type(expr), c_type(left_exp(expr)), c_type(right_exp(expr))),
    )
Example #4
0
def arithmetic_and_bitwise_operators(expr, symbol_table):
    expression = symbol_table['__ expression __']
    left_instrs = expression(left_exp(expr), symbol_table)
    right_instrs = expression(right_exp(expr), symbol_table)

    to_type = c_type(expr)
    if isinstance(to_type, ArrayType):
        to_type = PointerType(c_type(to_type), loc(c_type(expr)))

    return rules(arithmetic_and_bitwise_operators)[oper(expr)](
        cast(left_instrs, c_type(left_exp(expr)), to_type, loc(expr)),
        cast(right_instrs, c_type(right_exp(expr)), to_type, loc(expr)),
        loc(expr),
        (to_type, c_type(left_exp(expr)), c_type(right_exp(expr))),
    )
Example #5
0
def non_static_pointer_typed_definition_initialized_by_array_type(stmnt, symbol_table):
    stack, expression = utils.symbol_table.get_symbols(symbol_table, '__ stack __', '__ expression __')
    expr = declarations.initialization(stmnt)
    assert not isinstance(expr, (expressions.Initializer, expressions.CompoundLiteral))
    return chain(  # evaluate stack expression, which will push values on the stack and initialized pointer with sp
        cast(expression(expr, symbol_table), c_type(expr), c_type(stmnt), loc(stmnt)), load_stack_pointer(loc(stmnt))
    )
Example #6
0
def non_static_default_typed_definition(stmnt, symbol_table):
    return cast(
        symbol_table['__ expression __'](declarations.initialization(stmnt), symbol_table),
        c_type(declarations.initialization(stmnt)),
        c_type(stmnt),
        loc(stmnt)
    )
Example #7
0
def assign(expr, symbol_table):
    expression = symbol_table['__ expression __']
    return set_instr(
        chain(
            cast(expression(right_exp(expr), symbol_table), c_type(right_exp(expr)), c_type(expr), loc(expr)),
            # remove default Load instruction, emit Set instruction ...
            all_but_last(expression(left_exp(expr), symbol_table), Loads, loc(expr)),
        ),
        size_arrays_as_pointers(c_type(expr)),  # get the size exp returns an array make sure its treated as pointer ...
        loc(expr),
    )
Example #8
0
def array_subscript(expr, symbol_table):
    assert isinstance(c_type(left_exp(expr)), PointerType) and isinstance(
        c_type(right_exp(expr)), IntegralType)
    expression = symbol_table['__ expression __']
    l = loc(expr)
    addr_instrs = add(
        expression(left_exp(expr), symbol_table),
        multiply(
            cast(  # convert right expression to address type in order to properly multiply ...
                expression(right_exp(expr), symbol_table),
                c_type(right_exp(expr)), void_pointer_type, l),
            push(size(c_type(expr)), l),
            l),
        l,
    )  # Load value unless the return type is also an ArrayTyp
    return addr_instrs if isinstance(c_type(expr), ArrayType) \
        else load(addr_instrs, size_arrays_as_pointers(c_type(expr)), l)
Example #9
0
def array_subscript(expr, symbol_table):
    assert isinstance(c_type(left_exp(expr)), PointerType) and isinstance(c_type(right_exp(expr)), IntegralType)
    expression = symbol_table['__ expression __']
    l = loc(expr)
    addr_instrs = add(
        expression(left_exp(expr), symbol_table),
        multiply(
            cast(  # convert right expression to address type in order to properly multiply ...
                expression(right_exp(expr), symbol_table),
                c_type(right_exp(expr)),
                void_pointer_type,
                l
            ),
            push(size(c_type(expr)), l),
            l
        ),
        l,
    )   # Load value unless the return type is also an ArrayTyp
    return addr_instrs if isinstance(c_type(expr), ArrayType) \
        else load(addr_instrs, size_arrays_as_pointers(c_type(expr)), l)
Example #10
0
def return_statement(stmnt, symbol_table):
    # TODO: check if we can omit the setting the return value if if it is immediately removed ...
    return_type = c_type(c_type(symbol_table['__ CURRENT FUNCTION __']))
    assert not isinstance(c_type(return_type), ArrayType)
    if isinstance(return_type, VoidType) or not exp(stmnt):
     # just return if void type or expr is empty or size of expression is zero.
        return return_instrs(loc(stmnt))

    return chain(
        cast(symbol_table['__ expression __'](exp(stmnt), symbol_table), c_type(exp(stmnt)), return_type, loc(stmnt)),
        set_instr(
            load(
                add(load_base_stack_pointer(loc(stmnt)), push(size(void_pointer_type), loc(stmnt)), loc(stmnt)),
                size(void_pointer_type),
                loc(stmnt)
            ),
            size(return_type),
            loc(stmnt)
        ),
        # TODO: see if we can remove the following instr, since pop_frame will reset the base and stack pointers
        # allocate(-size(return_type), loc(stmnt)),  # Set leaves the value on the stack
        return_instrs(loc(stmnt))
    )