예제 #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)
    )
예제 #2
0
def element_section_pointer(expr, symbol_table):
    return element_instrs(
        c_type(c_type(left_exp(expr))),
        right_exp(expr),
        loc(expr),
        load_instrs=symbol_table['__ expression __'](left_exp(expr), symbol_table)
    )
예제 #3
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)
    )
예제 #4
0
파일: binary.py 프로젝트: mzsk/c_compiler
def logical_operators(expr, symbol_table):
    expression = symbol_table['__ expression __']
    return rules(logical_operators)[oper(expr)](
        expression(left_exp(expr), symbol_table), 
        expression(right_exp(expr), symbol_table),
        loc(expr),
        tuple(imap(size_arrays_as_pointers, imap(c_type, (expr, left_exp(expr), right_exp(expr)))))
    )
예제 #5
0
파일: binary.py 프로젝트: mzsk/c_compiler
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),
    )
예제 #6
0
파일: reduce.py 프로젝트: qs9816/c_compiler
def binary_exp(expr):
    if not all(imap(isinstance, (left_exp(expr), right_exp(expr)), repeat(ConstantExpression))):
        return expr

    exp_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))(loc(expr))
    l_exp, r_exp, location = exp(left_exp(expr)), exp(right_exp(expr)), loc(expr)

    # noinspection PyUnresolvedReferences  '1 + 2 - 3 * 7 / 4'
    return binary_exp.rules[oper(expr)](
        expr=expr, left_exp=l_exp, right_exp=r_exp, location=location, exp_type=exp_type
    )
예제 #7
0
파일: binary.py 프로젝트: mzsk/c_compiler
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))),
    )
예제 #8
0
파일: binary.py 프로젝트: mzsk/c_compiler
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))),
    )
예제 #9
0
def binary_exp(expr):
    if not all(
            imap(isinstance, (left_exp(expr), right_exp(expr)),
                 repeat(ConstantExpression))):
        return expr

    exp_type = max(imap(c_type, (left_exp(expr), right_exp(expr))))(loc(expr))
    l_exp, r_exp, location = exp(left_exp(expr)), exp(
        right_exp(expr)), loc(expr)

    # noinspection PyUnresolvedReferences  '1 + 2 - 3 * 7 / 4'
    return binary_exp.rules[oper(expr)](expr=expr,
                                        left_exp=l_exp,
                                        right_exp=r_exp,
                                        location=location,
                                        exp_type=exp_type)
예제 #10
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)
예제 #11
0
파일: binary.py 프로젝트: qs9816/c_compiler
def subtraction_expression(_exp):
    if is_binary_pointer_expression(_exp):  # if subtracting two pointers, then the return type is a LongType
        return BinaryExpression(
            left_exp(_exp), oper(_exp), right_exp(_exp),
            LongType(LongType(location=loc(_exp)), unsigned=True, location=loc(_exp)),
            location=loc(_exp)
        )
    return _exp
예제 #12
0
파일: binary.py 프로젝트: mzsk/c_compiler
def simple_numeric_assignment_no_casting(expr, symbol_table, operation):
    expression = symbol_table['__ expression __']
    # used when the left operand is an identifier so we can re-emit binaries instead of using expensive Dup instr
    return set_instr(
        chain(
            operation(
                expression(left_exp(expr), symbol_table),
                expression(right_exp(expr), symbol_table),
                loc(expr),
                tuple(imap(c_type, (expr, left_exp(expr), right_exp(expr))))
            ),
            expression(
                AddressOfExpression(left_exp(expr), PointerType(c_type(right_exp(expr)), loc(expr)), loc(expr)),
                symbol_table,
            )
        ),
        size(c_type(expr)),
        loc(expr),
    )
예제 #13
0
파일: binary.py 프로젝트: mzsk/c_compiler
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),
    )
예제 #14
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)
예제 #15
0
파일: binary.py 프로젝트: mzsk/c_compiler
def subtraction_expression(_exp):
    if is_binary_pointer_expression(
            _exp
    ):  # if subtracting two pointers, then the return type is a LongType
        return BinaryExpression(left_exp(_exp),
                                oper(_exp),
                                right_exp(_exp),
                                LongType(LongType(location=loc(_exp)),
                                         unsigned=True,
                                         location=loc(_exp)),
                                location=loc(_exp))
    return _exp
예제 #16
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
    )
예제 #17
0
def ternary_expression(expr, symbol_table):
    if_false_instr, end_of_conditional_instr = Pass(loc(expr)), Pass(loc(expr))
    expression = symbol_table['__ expression __']
    return chain(
        get_jump_false(size_arrays_as_pointers(c_type(exp(expr))))(expression(
            exp(expr), symbol_table), Offset(if_false_instr, loc(expr)),
                                                                   loc(expr)),
        expression(left_exp(expr), symbol_table),
        relative_jump(
            Offset(end_of_conditional_instr, loc(end_of_conditional_instr)),
            loc(expr)),
        (if_false_instr, ),
        expression(right_exp(expr), symbol_table),
        (end_of_conditional_instr, ),
    )
예제 #18
0
def ternary_expression(expr, symbol_table):
    if_false_instr, end_of_conditional_instr = Pass(loc(expr)), Pass(loc(expr))
    expression = symbol_table['__ expression __']
    return chain(
        get_jump_false(size_arrays_as_pointers(c_type(exp(expr))))(
            expression(exp(expr), symbol_table),
            Offset(if_false_instr, loc(expr)),
            loc(expr)
        ),
        expression(left_exp(expr), symbol_table),
        relative_jump(Offset(end_of_conditional_instr, loc(end_of_conditional_instr)), loc(expr)),
        (if_false_instr,),
        expression(right_exp(expr), symbol_table),
        (end_of_conditional_instr,),
    )
예제 #19
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)
예제 #20
0
파일: binary.py 프로젝트: mzsk/c_compiler
def is_binary_pointer_expression(_exp):
    return all(
        imap(
            isinstance,
            imap(c_type, (left_exp(_exp, None), right_exp(_exp, None)),
                 repeat(None)), repeat(PointerType)))
예제 #21
0
파일: binary.py 프로젝트: qs9816/c_compiler
def is_binary_pointer_expression(_exp):
    return all(imap(
        isinstance, imap(c_type, (left_exp(_exp, None), right_exp(_exp, None)), repeat(None)), repeat(PointerType)
    ))
예제 #22
0
파일: binary.py 프로젝트: qs9816/c_compiler
def integral_type(tokens, symbol_table, l_exp):
    exp = get_binary_expression(tokens, symbol_table, l_exp, assignment_expression, IntegralType)
    return CompoundAssignmentExpression(left_exp(exp), oper(exp), right_exp(exp), c_type(l_exp)(loc(exp)), loc(exp))
예제 #23
0
def element_section_pointer(expr, symbol_table):
    return element_instrs(c_type(c_type(left_exp(expr))),
                          right_exp(expr),
                          loc(expr),
                          load_instrs=symbol_table['__ expression __'](
                              left_exp(expr), symbol_table))
예제 #24
0
파일: binary.py 프로젝트: mzsk/c_compiler
def integral_type(tokens, symbol_table, l_exp):
    exp = get_binary_expression(tokens, symbol_table, l_exp,
                                assignment_expression, IntegralType)
    return CompoundAssignmentExpression(left_exp(exp), oper(exp),
                                        right_exp(exp),
                                        c_type(l_exp)(loc(exp)), loc(exp))