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 push_frame(
        arguments_instrs=(),
        location=LocationNotSet,
        total_size_of_arguments=0,
        omit_pointer_for_return_value=False,
):
    return chain(
        load_base_stack_pointer(location),  # save previous base stack pointer ...
        arguments_instrs,
        # Pointer to where to store return values, if applicable (ie non-zero return size)...
        () if omit_pointer_for_return_value else
        # calculate pointer for ret value, excluding base pointer ...
        add(load_stack_pointer(location), push((total_size_of_arguments + size(void_pointer_type)), location), location)
    )
Exemple #4
0
def call_function(function_call_expr, symbol_table):
    l, expr = loc(function_call_expr), left_exp(function_call_expr)
    return chain(  # if expression is a simple identifier of function type, no need for AbsoluteJump, use RelativeJump
        set_base_stack_pointer(load_stack_pointer(l), l),
        relative_jump(Offset(symbol_table[name(expr)].get_address_obj(l).obj, l), l),
    ) if isinstance(expr, IdentifierExpression) and isinstance(c_type(expr), FunctionType) else absolute_jump(
        chain(
            symbol_table['__ expression __'](expr, symbol_table),   # load callee address
            # calculate new base stack pointer excluding the callees address ...
            # give the callee a new frame... if we where to reset the base stack ptr before evaluating the left_expr
            # we run the risk of failing to properly load function address if it was store as a local function pointer
            set_base_stack_pointer(add(load_stack_pointer(l), push(size(void_pointer_type), l), l), l)
        ),
        l
    )
Exemple #5
0
def push_frame(
    arguments_instrs=(),
    location=LocationNotSet,
    total_size_of_arguments=0,
    omit_pointer_for_return_value=False,
):
    return chain(
        load_base_stack_pointer(
            location),  # save previous base stack pointer ...
        arguments_instrs,
        # Pointer to where to store return values, if applicable (ie non-zero return size)...
        () if omit_pointer_for_return_value else
        # calculate pointer for ret value, excluding base pointer ...
        add(
            load_stack_pointer(location),
            push((total_size_of_arguments +
                  size(void_pointer_type)), location), location))
Exemple #6
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)
Exemple #7
0
def call_function(function_call_expr, symbol_table):
    l, expr = loc(function_call_expr), left_exp(function_call_expr)
    return chain(  # if expression is a simple identifier of function type, no need for AbsoluteJump, use RelativeJump
        set_base_stack_pointer(load_stack_pointer(l), l),
        relative_jump(
            Offset(symbol_table[name(expr)].get_address_obj(l).obj, l), l),
    ) if isinstance(expr, IdentifierExpression) and isinstance(
        c_type(expr), FunctionType
    ) else absolute_jump(
        chain(
            symbol_table['__ expression __'](
                expr, symbol_table),  # load callee address
            # calculate new base stack pointer excluding the callees address ...
            # give the callee a new frame... if we where to reset the base stack ptr before evaluating the left_expr
            # we run the risk of failing to properly load function address if it was store as a local function pointer
            set_base_stack_pointer(
                add(load_stack_pointer(l), push(size(void_pointer_type), l),
                    l), l)),
        l)
Exemple #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)
Exemple #9
0
def pop_frame(location=LocationNotSet,
              total_size_of_arguments=0,
              omit_pointer_for_return_value=False):
    # return pop_frame_instr(location)  # method 1 requires special instruction that has to manage blocks

    # method 2 (5 instructions LoadBaseStackPtr, Push, Add, SetStackPtr, SetBaseStackPtr)
    # method 2 seems to be faster even though it has an extra instruction compare to method 3,
    # not really sure why ... probably because the optimizer is removing some of them

    return set_base_stack_pointer(
        set_stack_pointer(
            add(
                # remove parameters and ret addr ...
                load_base_stack_pointer(location),
                push(  # remove parameters, ret address pointer, and ptr for ret value if it was emitted ...
                    sum((total_size_of_arguments, size(void_pointer_type),
                         (not omit_pointer_for_return_value) *
                         size(void_pointer_type))), location),
                location),
            location),
        location)
Exemple #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))
    )
Exemple #11
0
def pop_frame(location=LocationNotSet, total_size_of_arguments=0, omit_pointer_for_return_value=False):
    # return pop_frame_instr(location)  # method 1 requires special instruction that has to manage blocks

    # method 2 (5 instructions LoadBaseStackPtr, Push, Add, SetStackPtr, SetBaseStackPtr)
    # method 2 seems to be faster even though it has an extra instruction compare to method 3,
    # not really sure why ... probably because the optimizer is removing some of them

    return set_base_stack_pointer(
        set_stack_pointer(
            add(
                # remove parameters and ret addr ...
                load_base_stack_pointer(location),
                push(    # remove parameters, ret address pointer, and ptr for ret value if it was emitted ...
                    sum((
                        total_size_of_arguments, size(void_pointer_type),
                        (not omit_pointer_for_return_value) * size(void_pointer_type))),
                    location
                ),
                location
            ),
            location
        ),
        location
    )
Exemple #12
0
 def load_address(self, location):
     return add(load_base_stack_pointer(location),
                push(self.offset, location), location)
Exemple #13
0
def element_instrs(struct_obj, member_name, location, load_instrs=iter(())):
    instrs = add(load_instrs, push(struct_member_offset(struct_obj, member_name), location), location)
    return instrs if isinstance(c_type(struct_obj.members[member_name]), ArrayType) else \
        load(instrs, size_arrays_as_pointers(c_type(struct_obj.members[member_name])), location)
Exemple #14
0
def element_instrs(struct_obj, member_name, location, load_instrs=iter(())):
    instrs = add(load_instrs,
                 push(struct_member_offset(struct_obj, member_name), location),
                 location)
    return instrs if isinstance(c_type(struct_obj.members[member_name]), ArrayType) else \
        load(instrs, size_arrays_as_pointers(c_type(struct_obj.members[member_name])), location)
Exemple #15
0
 def load_address(self, location):
     return add(load_base_stack_pointer(location), push(self.offset, location), location)