Example #1
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 #2
0
def get_declaration_or_definition(decl, storage_class):
    _ = initialization(decl) and isinstance(storage_class, Extern) and raise_error(
        '{l} {ident} has both initialization expr and extern storage class'.format(l=loc(decl), ident=name(decl)))

    if isinstance(c_type(decl), (FunctionType, StructType)) and not name(decl) or isinstance(storage_class, Extern):
        return Declaration(name(decl), c_type(decl), loc(decl), storage_class)

    return Definition(name(decl), c_type(decl), initialization(decl), loc(decl), storage_class or Auto(loc(decl)))
Example #3
0
def get_declaration_or_definition(decl, storage_class):
    _ = initialization(decl) and isinstance(
        storage_class, Extern) and raise_error(
            '{l} {ident} has both initialization expr and extern storage class'
            .format(l=loc(decl), ident=name(decl)))

    if isinstance(c_type(decl),
                  (FunctionType, StructType)) and not name(decl) or isinstance(
                      storage_class, Extern):
        return Declaration(name(decl), c_type(decl), loc(decl), storage_class)

    return Definition(name(decl), c_type(decl), initialization(decl),
                      loc(decl), storage_class or Auto(loc(decl)))
Example #4
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 #5
0
def function_definition(dec, symbol_table):
    """
    Function Call Convention:
        Allocate enough space on the stack for the return type.

        Push a new Frame (saves (base & stack ptr))
        Push all parameters on the stack from right to left. (The values won't be pop but referenced on stack (+) ...)
        Calculate & Push pointer where to return value.

        Push pointer where to store return value.
        Push the return Address so the callee knows where to return to.
        (Reset Base pointer) creating a new Frame.
        Jump to callee code segment

        callee references values passed on the stack by pushing the base_stack_pointer,
        (+offsets) for previous frame and (-offset) for current frame ...

        Callee will place the return value in the specified pointer.
        Caller Pops frame, and uses the set (returned) value.
    """
    symbol = Code(name(dec), None, None, dec.storage_class, loc(dec))
    symbol_table[name(dec)] = bind_load_instructions(dec)  # bind load/reference instructions, add to symbol table.
    symbol_table[name(dec)].symbol = symbol

    def binaries(body, symbol_table):
        symbol_table = push(symbol_table)
        symbol_table['__ stack __'] = Stack()  # Each function call has its own Frame which is nothing more than a stack

        # Skip return address ...
        offset = size_arrays_as_pointers(void_pointer_type) + (
            # if function has zero return size then the return pointer will be omitted ...
            size_arrays_as_pointers(void_pointer_type) *
            bool(size_arrays_as_pointers(c_type(c_type(dec)), overrides={VoidType: 0}))
        )

        for parameter in c_type(dec):
            # monkey patch declarator objects add Load commands according to stack state; add to symbol table.
            symbol_table[name(parameter)] = bind_instructions(parameter, offset)
            assert not type(parameter) is ArrayType  # TODO: fix this.
            offset += size_arrays_as_pointers(c_type(parameter))

        symbol_table.update(
            izip(('__ CURRENT FUNCTION __', '__ LABELS __', '__ GOTOS __'), (dec, SymbolTable(), defaultdict(list)))
        )

        def pop_symbol_table(symbol_table, location=loc(dec)):  # pop symbol table once all binaries have being emitted
            yield (pop(symbol_table) or 1) and Pass(location)

        return chain(   # body of function ...
            chain.from_iterable(imap(symbol_table['__ statement __'], chain.from_iterable(body), repeat(symbol_table))),
            return_instrs(loc(dec)),        # default return instructions, in case one was not giving ...
            pop_symbol_table(symbol_table)  # pop symbol_table once complete ...
        )

    symbol.binaries = binaries(initialization(dec), symbol_table)
    return symbol
Example #6
0
def function_definition(dec, symbol_table):
    """
    Function Call Convention:
        Allocate enough space on the stack for the return type.

        Push a new Frame (saves (base & stack ptr))
        Push all parameters on the stack from right to left. (The values won't be pop but referenced on stack (+) ...)
        Calculate & Push pointer where to return value.

        Push pointer where to store return value.
        Push the return Address so the callee knows where to return to.
        (Reset Base pointer) creating a new Frame.
        Jump to callee code segment

        callee references values passed on the stack by pushing the base_stack_pointer,
        (+offsets) for previous frame and (-offset) for current frame ...

        Callee will place the return value in the specified pointer.
        Caller Pops frame, and uses the set (returned) value.
    """
    symbol = Code(name(dec), None, None, dec.storage_class, loc(dec))
    symbol_table[name(dec)] = bind_load_instructions(
        dec)  # bind load/reference instructions, add to symbol table.
    symbol_table[name(dec)].symbol = symbol

    def binaries(body, symbol_table):
        symbol_table = push(symbol_table)
        symbol_table['__ stack __'] = Stack(
        )  # Each function call has its own Frame which is nothing more than a stack

        # Skip return address ...
        offset = size_arrays_as_pointers(void_pointer_type) + (
            # if function has zero return size then the return pointer will be omitted ...
            size_arrays_as_pointers(void_pointer_type) * bool(
                size_arrays_as_pointers(c_type(c_type(dec)),
                                        overrides={VoidType: 0})))

        for parameter in c_type(dec):
            # monkey patch declarator objects add Load commands according to stack state; add to symbol table.
            symbol_table[name(parameter)] = bind_instructions(
                parameter, offset)
            assert not type(parameter) is ArrayType  # TODO: fix this.
            offset += size_arrays_as_pointers(c_type(parameter))

        symbol_table.update(
            izip(('__ CURRENT FUNCTION __', '__ LABELS __', '__ GOTOS __'),
                 (dec, SymbolTable(), defaultdict(list))))

        def pop_symbol_table(symbol_table, location=loc(
            dec)):  # pop symbol table once all binaries have being emitted
            yield (pop(symbol_table) or 1) and Pass(location)

        return chain(  # body of function ...
            chain.from_iterable(
                imap(symbol_table['__ statement __'],
                     chain.from_iterable(body), repeat(symbol_table))),
            return_instrs(
                loc(dec)
            ),  # default return instructions, in case one was not giving ...
            pop_symbol_table(
                symbol_table)  # pop symbol_table once complete ...
        )

    symbol.binaries = binaries(initialization(dec), symbol_table)
    return symbol
Example #7
0
def non_static_pointer_typed_definition(stmnt, symbol_table):
    return rules(non_static_pointer_typed_definition)[type(c_type(declarations.initialization(stmnt)))](
        stmnt, symbol_table
    )